Compare commits

...

3 commits

15 changed files with 536 additions and 24 deletions

View file

@ -4,6 +4,7 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.api.OpenPGPApi; import org.bouncycastle.openpgp.api.OpenPGPApi;
import org.bouncycastle.openpgp.api.bc.BcOpenPGPApi; import org.bouncycastle.openpgp.api.bc.BcOpenPGPApi;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.pgpainless.bouncycastle.sop.operation.BCArmor; import org.pgpainless.bouncycastle.sop.operation.BCArmor;
import org.pgpainless.bouncycastle.sop.operation.BCDearmor; import org.pgpainless.bouncycastle.sop.operation.BCDearmor;
import org.pgpainless.bouncycastle.sop.operation.BCDecrypt; import org.pgpainless.bouncycastle.sop.operation.BCDecrypt;
@ -15,10 +16,12 @@ import org.pgpainless.bouncycastle.sop.operation.BCGenerateKey;
import org.pgpainless.bouncycastle.sop.operation.BCInlineSign; import org.pgpainless.bouncycastle.sop.operation.BCInlineSign;
import org.pgpainless.bouncycastle.sop.operation.BCInlineVerify; import org.pgpainless.bouncycastle.sop.operation.BCInlineVerify;
import org.pgpainless.bouncycastle.sop.operation.BCListProfiles; import org.pgpainless.bouncycastle.sop.operation.BCListProfiles;
import org.pgpainless.bouncycastle.sop.operation.BCMergeCerts;
import org.pgpainless.bouncycastle.sop.operation.BCVersion; import org.pgpainless.bouncycastle.sop.operation.BCVersion;
import sop.SOP; import sop.SOP;
import sop.exception.SOPGPException; import sop.exception.SOPGPException;
import sop.operation.Armor; import sop.operation.Armor;
import sop.operation.CertifyUserId;
import sop.operation.ChangeKeyPassword; import sop.operation.ChangeKeyPassword;
import sop.operation.Dearmor; import sop.operation.Dearmor;
import sop.operation.Decrypt; import sop.operation.Decrypt;
@ -31,7 +34,10 @@ import sop.operation.InlineDetach;
import sop.operation.InlineSign; import sop.operation.InlineSign;
import sop.operation.InlineVerify; import sop.operation.InlineVerify;
import sop.operation.ListProfiles; import sop.operation.ListProfiles;
import sop.operation.MergeCerts;
import sop.operation.RevokeKey; import sop.operation.RevokeKey;
import sop.operation.UpdateKey;
import sop.operation.ValidateUserId;
import sop.operation.Version; import sop.operation.Version;
import java.security.Security; import java.security.Security;
@ -136,4 +142,28 @@ public class BouncyCastleSOP implements SOP {
public InlineVerify inlineVerify() { public InlineVerify inlineVerify() {
return new BCInlineVerify(api); return new BCInlineVerify(api);
} }
@Nullable
@Override
public CertifyUserId certifyUserId() {
throw new SOPGPException.UnsupportedSubcommand("certify-userid is not implemented.");
}
@Nullable
@Override
public UpdateKey updateKey() {
throw new SOPGPException.UnsupportedSubcommand("update-key is not implemented.");
}
@Nullable
@Override
public MergeCerts mergeCerts() {
return new BCMergeCerts(api);
}
@Nullable
@Override
public ValidateUserId validateUserId() {
throw new SOPGPException.UnsupportedSubcommand("validate-userid is not implemented.");
}
} }

View file

@ -0,0 +1,74 @@
package org.pgpainless.bouncycastle.sop.operation;
import org.bouncycastle.openpgp.api.KeyPassphraseProvider;
import org.bouncycastle.openpgp.api.OpenPGPApi;
import org.bouncycastle.util.io.Streams;
import org.jetbrains.annotations.NotNull;
import sop.Ready;
import sop.exception.SOPGPException;
import sop.operation.CertifyUserId;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;
public class BCCertifyUserId
extends AbstractBCOperation
implements CertifyUserId {
private final KeyPassphraseProvider.DefaultKeyPassphraseProvider passphraseProvider =
new KeyPassphraseProvider.DefaultKeyPassphraseProvider();
private boolean armor = true;
private boolean requireSelfSig = true;
private final Set<String> userIds = new HashSet<>();
public BCCertifyUserId(OpenPGPApi api) {
super(api);
}
@NotNull
@Override
public Ready certs(@NotNull InputStream inputStream) throws SOPGPException.BadData, IOException, SOPGPException.CertUserIdNoMatch {
return new Ready() {
@Override
public void writeTo(@NotNull OutputStream outputStream) throws IOException {
Streams.pipeAll(inputStream, outputStream);
}
};
}
@NotNull
@Override
public CertifyUserId noArmor() throws SOPGPException.UnsupportedOption {
this.armor = false;
return this;
}
@NotNull
@Override
public CertifyUserId userId(@NotNull String s) throws SOPGPException.UnsupportedOption {
this.userIds.add(s.trim());
return this;
}
@NotNull
@Override
public CertifyUserId withKeyPassword(@NotNull byte[] bytes) throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
passphraseProvider.addPassphrase(new String(bytes).toCharArray());
return this;
}
@NotNull
@Override
public CertifyUserId noRequireSelfSig() throws SOPGPException.UnsupportedOption {
this.requireSelfSig = false;
return this;
}
@NotNull
@Override
public CertifyUserId keys(@NotNull InputStream inputStream) throws SOPGPException.BadData, IOException, SOPGPException.KeyIsProtected {
return this;
}
}

View file

@ -20,6 +20,7 @@ public class BCDetachedVerify
{ {
private final OpenPGPDetachedSignatureProcessor processor; private final OpenPGPDetachedSignatureProcessor processor;
private boolean hasCerts = false;
public BCDetachedVerify(OpenPGPApi api) public BCDetachedVerify(OpenPGPApi api)
{ {
@ -50,12 +51,16 @@ public class BCDetachedVerify
@Override @Override
public DetachedVerify cert(@NotNull InputStream inputStream) throws SOPGPException.BadData, IOException { public DetachedVerify cert(@NotNull InputStream inputStream) throws SOPGPException.BadData, IOException {
processor.addVerificationCertificate(parseCertificate(inputStream)); processor.addVerificationCertificate(parseCertificate(inputStream));
hasCerts = true;
return this; return this;
} }
@NotNull @NotNull
@Override @Override
public List<Verification> data(@NotNull InputStream inputStream) throws IOException, SOPGPException.NoSignature, SOPGPException.BadData { public List<Verification> data(@NotNull InputStream inputStream) throws IOException, SOPGPException.NoSignature, SOPGPException.BadData {
if (!hasCerts) {
throw new SOPGPException.MissingArg("No certificates provided for signature verification.");
}
List<OpenPGPSignature.OpenPGPDocumentSignature> signatures = processor.process(inputStream); List<OpenPGPSignature.OpenPGPDocumentSignature> signatures = processor.process(inputStream);
List<Verification> verifications = getVerifications(signatures); List<Verification> verifications = getVerifications(signatures);

View file

@ -31,6 +31,7 @@ public class BCEncrypt
private final OpenPGPMessageGenerator mGen; private final OpenPGPMessageGenerator mGen;
private final List<OpenPGPKey> signingKeys = new ArrayList<>(); private final List<OpenPGPKey> signingKeys = new ArrayList<>();
private int signatureMode = PGPSignature.BINARY_DOCUMENT; private int signatureMode = PGPSignature.BINARY_DOCUMENT;
private boolean hasEncryptionMethod = false;
public BCEncrypt(OpenPGPApi api) { public BCEncrypt(OpenPGPApi api) {
super(api); super(api);
@ -83,6 +84,7 @@ public class BCEncrypt
public Encrypt withPassword(@NotNull String s) public Encrypt withPassword(@NotNull String s)
throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption { throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
mGen.addEncryptionPassphrase(s.toCharArray()); mGen.addEncryptionPassphrase(s.toCharArray());
hasEncryptionMethod = true;
return this; return this;
} }
@ -92,6 +94,7 @@ public class BCEncrypt
throws SOPGPException.CertCannotEncrypt, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.BadData { throws SOPGPException.CertCannotEncrypt, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.BadData {
try { try {
mGen.addEncryptionCertificate(parseCertificate(inputStream)); mGen.addEncryptionCertificate(parseCertificate(inputStream));
hasEncryptionMethod = true;
} catch (InvalidEncryptionKeyException e) { } catch (InvalidEncryptionKeyException e) {
throw new SOPGPException.CertCannotEncrypt("Certificate cannot encrypt", e); throw new SOPGPException.CertCannotEncrypt("Certificate cannot encrypt", e);
} }
@ -109,6 +112,10 @@ public class BCEncrypt
@Override @Override
public ReadyWithResult<EncryptionResult> plaintext(@NotNull InputStream inputStream) public ReadyWithResult<EncryptionResult> plaintext(@NotNull InputStream inputStream)
throws SOPGPException.KeyIsProtected { throws SOPGPException.KeyIsProtected {
if (!hasEncryptionMethod) {
throw new SOPGPException.MissingArg("No encryption method provided.");
}
for (OpenPGPKey key : signingKeys) { for (OpenPGPKey key : signingKeys) {
try { try {
mGen.addSigningKey(key, new SignatureParameters.Callback() { mGen.addSigningKey(key, new SignatureParameters.Callback() {

View file

@ -7,6 +7,8 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.api.OpenPGPApi; import org.bouncycastle.openpgp.api.OpenPGPApi;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory; import org.bouncycastle.openpgp.bc.BcPGPObjectFactory;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import sop.Ready; import sop.Ready;
@ -16,6 +18,7 @@ import sop.operation.ExtractCert;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -33,29 +36,32 @@ public class BCExtractCert
@NotNull @NotNull
@Override @Override
public Ready key(@NotNull InputStream inputStream) throws IOException, SOPGPException.BadData { public Ready key(@NotNull InputStream inputStream) throws IOException, SOPGPException.BadData {
InputStream decodeIn = PGPUtil.getDecoderStream(inputStream); List<OpenPGPKey> keys = api.readKeyOrCertificate().parseKeys(inputStream);
PGPObjectFactory objFac = new BcPGPObjectFactory(decodeIn); List<OpenPGPCertificate> certs = new ArrayList<>();
PGPSecretKeyRing secretKeys = (PGPSecretKeyRing) objFac.nextObject(); for (OpenPGPKey key : keys) {
certs.add(key.toCertificate());
List<PGPPublicKey> list = new ArrayList<>();
Iterator<PGPPublicKey> iterator = secretKeys.getPublicKeys();
while (iterator.hasNext()) {
list.add(iterator.next());
} }
PGPPublicKeyRing publicKeys = new PGPPublicKeyRing(list);
return new Ready() { return new Ready() {
@Override @Override
public void writeTo(@NotNull OutputStream outputStream) throws IOException { public void writeTo(@NotNull OutputStream outputStream) throws IOException {
if (armor) { if (armor) {
ArmoredOutputStream aOut = ArmoredOutputStream.builder() if (certs.size() == 1) {
.clearHeaders() outputStream.write(certs.get(0).toAsciiArmoredString().getBytes(StandardCharsets.UTF_8));
.enableCRC(true) } else {
.build(outputStream); ArmoredOutputStream aOut = ArmoredOutputStream.builder()
publicKeys.encode(aOut); .clearHeaders()
aOut.close(); .enableCRC(true)
.build(outputStream);
for (OpenPGPCertificate cert : certs) {
aOut.write(cert.getEncoded());
}
aOut.close();
}
} else { } else {
publicKeys.encode(outputStream); for (OpenPGPCertificate cert : certs) {
outputStream.write(cert.getEncoded());
}
} }
} }
}; };

View file

@ -3,6 +3,7 @@ package org.pgpainless.bouncycastle.sop.operation;
import org.bouncycastle.openpgp.api.OpenPGPApi; import org.bouncycastle.openpgp.api.OpenPGPApi;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import sop.Profile; import sop.Profile;
import sop.exception.SOPGPException;
import sop.operation.ListProfiles; import sop.operation.ListProfiles;
import java.util.Collections; import java.util.Collections;
@ -22,7 +23,9 @@ public class BCListProfiles
switch (s) { switch (s) {
case "generate-key": case "generate-key":
return BCGenerateKey.PROFILES; return BCGenerateKey.PROFILES;
case "encrypt":
return Collections.emptyList();
} }
return Collections.emptyList(); throw new SOPGPException.UnsupportedProfile(s);
} }
} }

View file

@ -0,0 +1,105 @@
package org.pgpainless.bouncycastle.sop.operation;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.api.OpenPGPApi;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.jetbrains.annotations.NotNull;
import sop.Ready;
import sop.exception.SOPGPException;
import sop.operation.MergeCerts;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BCMergeCerts
extends AbstractBCOperation
implements MergeCerts {
private List<OpenPGPCertificate> updates = new ArrayList<>();
private boolean armor = true;
public BCMergeCerts(OpenPGPApi api) {
super(api);
}
@NotNull
@Override
public Ready baseCertificates(@NotNull InputStream inputStream) throws SOPGPException.BadData, IOException {
return new Ready() {
@Override
public void writeTo(@NotNull OutputStream outputStream) throws IOException {
Map<KeyIdentifier, OpenPGPCertificate> merged = new HashMap<>();
List<OpenPGPCertificate> baseCerts = api.readKeyOrCertificate().parseCertificates(inputStream);
// Merge base certs
for (OpenPGPCertificate base : baseCerts) {
OpenPGPCertificate existing = merged.get(base.getKeyIdentifier());
if (existing != null) {
try {
existing = OpenPGPCertificate.join(existing, base);
merged.put(existing.getKeyIdentifier(), existing);
} catch (PGPException e) {
throw new RuntimeException(e);
}
} else {
merged.put(base.getKeyIdentifier(), base);
}
}
// Merge updates
for (OpenPGPCertificate update : updates) {
OpenPGPCertificate existing = merged.get(update.getKeyIdentifier());
if (existing != null) {
try {
existing = OpenPGPCertificate.join(existing, update);
merged.put(existing.getKeyIdentifier(), existing);
} catch (PGPException e) {
throw new RuntimeException(e);
}
}
}
// output
if (armor) {
if (merged.size() == 1) {
outputStream.write(merged.values().iterator().next().toAsciiArmoredString().getBytes(StandardCharsets.UTF_8));
} else {
ArmoredOutputStream aOut = ArmoredOutputStream.builder()
.clearHeaders()
.build(outputStream);
for (OpenPGPCertificate cert : merged.values()) {
aOut.write(cert.getEncoded());
}
aOut.close();
}
} else {
for (OpenPGPCertificate cert : merged.values()) {
outputStream.write(cert.getEncoded());
}
}
}
};
}
@NotNull
@Override
public MergeCerts noArmor() throws SOPGPException.UnsupportedOption {
armor = false;
return this;
}
@NotNull
@Override
public MergeCerts updates(@NotNull InputStream inputStream) throws SOPGPException.BadData, IOException {
this.updates.addAll(api.readKeyOrCertificate().parseCertificates(inputStream));
return this;
}
}

View file

@ -0,0 +1,95 @@
package org.pgpainless.bouncycastle.sop.operation;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.api.KeyPassphraseProvider;
import org.bouncycastle.openpgp.api.OpenPGPApi;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.api.OpenPGPKeyEditor;
import org.bouncycastle.openpgp.api.exception.KeyPassphraseException;
import org.jetbrains.annotations.NotNull;
import sop.Ready;
import sop.exception.SOPGPException;
import sop.operation.RevokeKey;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class BCRevokeKey extends AbstractBCOperation implements RevokeKey {
private boolean armor = true;
private final KeyPassphraseProvider.DefaultKeyPassphraseProvider passphraseProvider =
new KeyPassphraseProvider.DefaultKeyPassphraseProvider();
public BCRevokeKey(OpenPGPApi api) {
super(api);
}
@NotNull
@Override
public Ready keys(@NotNull InputStream inputStream) {
return new Ready() {
@Override
public void writeTo(@NotNull OutputStream outputStream) throws IOException {
List<OpenPGPKey> keys;
try {
keys = api.readKeyOrCertificate().parseKeys(inputStream);
} catch (IOException e) {
throw new SOPGPException.BadData(e);
}
List<OpenPGPCertificate> revoked = new ArrayList<>();
for (OpenPGPKey key : keys) {
try {
OpenPGPKeyEditor editor = api.editKey(key, passphraseProvider);
editor.revokeKey();
revoked.add(editor.done().toCertificate());
} catch (KeyPassphraseException e) {
throw new SOPGPException.KeyIsProtected("Cannot unlock secret key", e);
} catch (PGPException e) {
throw new RuntimeException(e);
}
}
if (armor) {
if (revoked.size() == 1) {
outputStream.write(revoked.get(0).toAsciiArmoredString().getBytes(StandardCharsets.UTF_8));
} else {
ArmoredOutputStream aOut = ArmoredOutputStream.builder()
.clearHeaders()
.build(outputStream);
for (OpenPGPCertificate cert : revoked) {
aOut.write(cert.getEncoded());
}
aOut.close();
}
} else {
for (OpenPGPCertificate cert : revoked) {
outputStream.write(cert.getEncoded());
}
}
}
};
}
@NotNull
@Override
public RevokeKey noArmor() {
armor = false;
return this;
}
@NotNull
@Override
public RevokeKey withKeyPassword(@NotNull byte[] bytes)
throws SOPGPException.UnsupportedOption, SOPGPException.PasswordNotHumanReadable {
passphraseProvider.addPassphrase(new String(bytes).toCharArray());
return this;
}
}

View file

@ -0,0 +1,77 @@
package org.pgpainless.bouncycastle.sop.operation;
import org.bouncycastle.openpgp.api.KeyPassphraseProvider;
import org.bouncycastle.openpgp.api.OpenPGPApi;
import org.bouncycastle.util.io.Streams;
import org.jetbrains.annotations.NotNull;
import sop.Ready;
import sop.exception.SOPGPException;
import sop.operation.UpdateKey;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class BCUpdateKey
extends AbstractBCOperation
implements UpdateKey {
private final KeyPassphraseProvider.DefaultKeyPassphraseProvider passphraseProvider =
new KeyPassphraseProvider.DefaultKeyPassphraseProvider();
private boolean armor = true;
private boolean signingOnly = false;
private boolean addCapabilities = true;
public BCUpdateKey(OpenPGPApi api) {
super(api);
}
@NotNull
@Override
public Ready key(@NotNull InputStream inputStream)
throws SOPGPException.BadData, IOException, SOPGPException.KeyIsProtected, SOPGPException.PrimaryKeyBad {
return new Ready() {
@Override
public void writeTo(@NotNull OutputStream outputStream) throws IOException {
Streams.pipeAll(inputStream, outputStream);
}
};
}
@NotNull
@Override
public UpdateKey noArmor() {
armor = false;
return this;
}
@NotNull
@Override
public UpdateKey signingOnly()
throws SOPGPException.UnsupportedOption {
signingOnly = true;
return this;
}
@NotNull
@Override
public UpdateKey noAddedCapabilities()
throws SOPGPException.UnsupportedOption {
addCapabilities = false;
return this;
}
@NotNull
@Override
public UpdateKey withKeyPassword(@NotNull byte[] bytes)
throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
passphraseProvider.addPassphrase(new String(bytes).toCharArray());
return this;
}
@NotNull
@Override
public UpdateKey mergeCerts(@NotNull InputStream inputStream)
throws SOPGPException.UnsupportedOption, SOPGPException.BadData, IOException {
return this;
}
}

View file

@ -0,0 +1,87 @@
package org.pgpainless.bouncycastle.sop.operation;
import org.bouncycastle.openpgp.PGPSignatureException;
import org.bouncycastle.openpgp.api.OpenPGPApi;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.jetbrains.annotations.NotNull;
import sop.exception.SOPGPException;
import sop.operation.ValidateUserId;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class BCValidateUserId
extends AbstractBCOperation
implements ValidateUserId {
private boolean validateSpecOnly = false;
private Date validateAt = new Date();
private final List<String> userIds = new ArrayList<>();
private final List<OpenPGPCertificate> authorities = new ArrayList<>();
public BCValidateUserId(OpenPGPApi api) {
super(api);
}
@NotNull
@Override
public ValidateUserId addrSpecOnly()
throws SOPGPException.UnsupportedOption {
validateSpecOnly = true;
return this;
}
@NotNull
@Override
public ValidateUserId userId(@NotNull String s) {
userIds.add(s.trim());
return this;
}
@NotNull
@Override
public ValidateUserId authorities(@NotNull InputStream inputStream)
throws SOPGPException.BadData, IOException {
authorities.addAll(api.readKeyOrCertificate().parseCertificates(inputStream));
return this;
}
@Override
public boolean subjects(@NotNull InputStream inputStream)
throws SOPGPException.BadData, IOException, SOPGPException.CertUserIdNoMatch {
List<OpenPGPCertificate> certificates = api.readKeyOrCertificate().parseCertificates(inputStream);
for (OpenPGPCertificate certificate : certificates) {
for (String userId : userIds) {
OpenPGPCertificate.OpenPGPUserId uid = certificate.getUserId(userId);
if (!uid.isBoundAt(validateAt)) {
return false;
}
for (OpenPGPCertificate authority : authorities) {
OpenPGPCertificate.OpenPGPSignatureChain certification = uid.getCertificationBy(authority);
if (certification == null) {
throw new SOPGPException.CertUserIdNoMatch("Could not find certification for UserID '" + userId + "'");
}
try {
if (!certification.isValid()) {
return false;
}
} catch (PGPSignatureException e) {
return false;
}
}
}
}
return true;
}
@NotNull
@Override
public ValidateUserId validateAt(@NotNull Date date) {
validateAt = date;
return this;
}
}

View file

@ -41,7 +41,9 @@ public class BCVersion
@NotNull @NotNull
@Override @Override
public String getExtendedVersion() { public String getExtendedVersion() {
return ""; return getName() + " " + getVersion() + "\n"
+ getBackendVersion() + "\n"
+ "sop-java " + getSopJavaVersion();
} }
@Override @Override

View file

@ -0,0 +1,7 @@
package org.pgpainless.bouncycastle.sop.operation;
import sop.testsuite.operation.CertifyValidateUserIdTest;
public class BCSopCertifyValidateUserIdTest extends CertifyValidateUserIdTest {
}

View file

@ -0,0 +1,7 @@
package org.pgpainless.bouncycastle.sop.operation;
import sop.testsuite.operation.ListProfilesTest;
public class BCSopListProfilesTest extends ListProfilesTest {
}

View file

@ -0,0 +1,7 @@
package org.pgpainless.bouncycastle.sop.operation;
import sop.testsuite.operation.MergeCertsTest;
public class BCSopMergeCertsTest extends MergeCertsTest {
}

12
pom.xml
View file

@ -33,32 +33,32 @@
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId> <artifactId>bcprov-jdk18on</artifactId>
<version>1.80-SNAPSHOT</version> <version>1.82-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk18on</artifactId> <artifactId>bcpg-jdk18on</artifactId>
<version>1.80-SNAPSHOT</version> <version>1.82-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcutil-jdk18on</artifactId> <artifactId>bcutil-jdk18on</artifactId>
<version>1.80-SNAPSHOT</version> <version>1.82-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.pgpainless</groupId> <groupId>org.pgpainless</groupId>
<artifactId>sop-java</artifactId> <artifactId>sop-java</artifactId>
<version>10.1.1-SNAPSHOT</version> <version>14.0.1-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.pgpainless</groupId> <groupId>org.pgpainless</groupId>
<artifactId>sop-java-picocli</artifactId> <artifactId>sop-java-picocli</artifactId>
<version>10.1.1-SNAPSHOT</version> <version>14.0.1-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.pgpainless</groupId> <groupId>org.pgpainless</groupId>
<artifactId>sop-java-testfixtures</artifactId> <artifactId>sop-java-testfixtures</artifactId>
<version>10.1.1-SNAPSHOT</version> <version>14.0.1-SNAPSHOT</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>