mirror of
https://codeberg.org/PGPainless/bc-sop.git
synced 2025-09-09 19:29:41 +02:00
Initial commit
This commit is contained in:
commit
1d697eb682
18 changed files with 742 additions and 0 deletions
35
bcsop/pom.xml
Normal file
35
bcsop/pom.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.pgpainless</groupId>
|
||||
<artifactId>bc-sop</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>bcsop</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.pgpainless</groupId>
|
||||
<artifactId>sop-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk18on</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpg-jdk18on</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,99 @@
|
|||
package org.pgpainless.bouncycastle.sop;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.pgpainless.bouncycastle.sop.operation.*;
|
||||
import sop.SOP;
|
||||
import sop.operation.*;
|
||||
|
||||
public class BouncyCastleSOP implements SOP {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Armor armor() {
|
||||
return new BCArmor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GenerateKey generateKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ExtractCert extractCert() {
|
||||
return new BCExtractCert();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DetachedSign detachedSign() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public InlineSign inlineSign() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public InlineDetach inlineDetach() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Encrypt encrypt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Decrypt decrypt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Dearmor dearmor() {
|
||||
return new BCDearmor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ListProfiles listProfiles() {
|
||||
return new BCListProfiles();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public RevokeKey revokeKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ChangeKeyPassword changeKeyPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Version version() {
|
||||
return new BCVersion();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DetachedVerify detachedVerify() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public InlineVerify inlineVerify() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.pgpainless.bouncycastle.sop.operation;
|
||||
|
||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import sop.Ready;
|
||||
import sop.enums.ArmorLabel;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Armor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class BCArmor implements Armor {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ready data(@NotNull InputStream inputStream) throws SOPGPException.BadData, IOException {
|
||||
return new Ready() {
|
||||
@Override
|
||||
public void writeTo(@NotNull OutputStream outputStream) throws IOException {
|
||||
ArmoredOutputStream aOut = ArmoredOutputStream.builder()
|
||||
.clearHeaders()
|
||||
.build(outputStream);
|
||||
Streams.pipeAll(inputStream, aOut);
|
||||
aOut.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Armor label(@NotNull ArmorLabel armorLabel) throws SOPGPException.UnsupportedOption {
|
||||
throw new SOPGPException.UnsupportedOption("Custom labels not supported.");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.pgpainless.bouncycastle.sop.operation;
|
||||
|
||||
import org.bouncycastle.bcpg.ArmoredInputStream;
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import sop.Ready;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Dearmor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class BCDearmor implements Dearmor {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ready data(@NotNull InputStream inputStream) throws SOPGPException.BadData, IOException {
|
||||
return new Ready() {
|
||||
@Override
|
||||
public void writeTo(@NotNull OutputStream outputStream) throws IOException {
|
||||
ArmoredInputStream aIn = new ArmoredInputStream(inputStream);
|
||||
Streams.pipeAll(aIn, outputStream);
|
||||
aIn.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
package org.pgpainless.bouncycastle.sop.operation;
|
||||
|
||||
import org.bouncycastle.openpgp.*;
|
||||
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory;
|
||||
import org.bouncycastle.openpgp.operator.SessionKeyDataDecryptorFactory;
|
||||
import org.bouncycastle.openpgp.operator.bc.BcSessionKeyDataDecryptorFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import sop.DecryptionResult;
|
||||
import sop.ReadyWithResult;
|
||||
import sop.SessionKey;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Decrypt;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class BCDecrypt implements Decrypt {
|
||||
|
||||
private Date notBefore = new Date(Long.MAX_VALUE); // end of time
|
||||
private Date notAfter = new Date(); // now
|
||||
private final List<PGPSessionKey> sessionKeys = new ArrayList<>();
|
||||
private final List<String> messagePassphrases = new ArrayList<>();
|
||||
private final List<PGPPublicKeyRing> verificationCerts = new ArrayList<>();
|
||||
private final List<PGPSecretKeyRing> encryptionKeys = new ArrayList<>();
|
||||
private final List<String> encryptionKeyPassphrases = new ArrayList<>();
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ReadyWithResult<DecryptionResult> ciphertext(@NotNull InputStream inputStream) throws SOPGPException.BadData, SOPGPException.MissingArg, SOPGPException.CannotDecrypt, SOPGPException.KeyIsProtected, IOException {
|
||||
return new ReadyWithResult<DecryptionResult>() {
|
||||
@Override
|
||||
public DecryptionResult writeTo(@NotNull OutputStream outputStream) throws IOException, SOPGPException {
|
||||
InputStream in = PGPUtil.getDecoderStream(inputStream);
|
||||
PGPObjectFactory objFac = new BcPGPObjectFactory(in);
|
||||
Object next = objFac.nextObject();
|
||||
|
||||
if (next instanceof PGPEncryptedDataList) {
|
||||
PGPEncryptedDataList encDataList = (PGPEncryptedDataList) next;
|
||||
|
||||
if (!sessionKeys.isEmpty()) {
|
||||
PGPSessionKeyEncryptedData sesKeyEnc = encDataList.extractSessionKeyEncryptedData();
|
||||
SessionKeyDataDecryptorFactory decFac = new BcSessionKeyDataDecryptorFactory(sessionKeys.get(0));
|
||||
try {
|
||||
in = sesKeyEnc.getDataStream(decFac);
|
||||
objFac = new BcPGPObjectFactory(in);
|
||||
next = objFac.nextObject();
|
||||
} catch (PGPException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
for (PGPEncryptedData encData : encDataList) {
|
||||
if (encData instanceof PGPPublicKeyEncryptedData) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Decrypt verifyNotBefore(@NotNull Date date) throws SOPGPException.UnsupportedOption {
|
||||
this.notBefore = date;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Decrypt verifyNotAfter(@NotNull Date date) throws SOPGPException.UnsupportedOption {
|
||||
this.notAfter = date;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Decrypt verifyWithCert(@NotNull InputStream inputStream) throws SOPGPException.BadData, SOPGPException.UnsupportedAsymmetricAlgo, IOException {
|
||||
InputStream decodeIn = PGPUtil.getDecoderStream(inputStream);
|
||||
PGPObjectFactory objFac = new BcPGPObjectFactory(decodeIn);
|
||||
PGPPublicKeyRing cert = (PGPPublicKeyRing) objFac.nextObject();
|
||||
verificationCerts.add(cert);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Decrypt withSessionKey(@NotNull SessionKey sessionKey) throws SOPGPException.UnsupportedOption {
|
||||
this.sessionKeys.add(new PGPSessionKey(sessionKey.getAlgorithm(), sessionKey.getKey()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Decrypt withPassword(@NotNull String s) throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
|
||||
this.messagePassphrases.add(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Decrypt withKey(@NotNull InputStream inputStream) throws SOPGPException.BadData, SOPGPException.UnsupportedAsymmetricAlgo, IOException {
|
||||
InputStream decodeIn = PGPUtil.getDecoderStream(inputStream);
|
||||
PGPObjectFactory objFac = new BcPGPObjectFactory(decodeIn);
|
||||
PGPSecretKeyRing key = (PGPSecretKeyRing) objFac.nextObject();
|
||||
this.encryptionKeys.add(key);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Decrypt withKeyPassword(@NotNull byte[] bytes) throws SOPGPException.UnsupportedOption, SOPGPException.PasswordNotHumanReadable {
|
||||
String passphrase = new String(bytes);
|
||||
this.encryptionKeyPassphrases.add(passphrase);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package org.pgpainless.bouncycastle.sop.operation;
|
||||
|
||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
||||
import org.bouncycastle.openpgp.*;
|
||||
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import sop.Ready;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.ExtractCert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class BCExtractCert implements ExtractCert {
|
||||
|
||||
private boolean armor = true;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ready key(@NotNull InputStream inputStream) throws IOException, SOPGPException.BadData {
|
||||
InputStream decodeIn = PGPUtil.getDecoderStream(inputStream);
|
||||
PGPObjectFactory objFac = new BcPGPObjectFactory(decodeIn);
|
||||
PGPSecretKeyRing secretKeys = (PGPSecretKeyRing) objFac.nextObject();
|
||||
|
||||
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() {
|
||||
@Override
|
||||
public void writeTo(@NotNull OutputStream outputStream) throws IOException {
|
||||
if (armor) {
|
||||
ArmoredOutputStream aOut = ArmoredOutputStream.builder()
|
||||
.clearHeaders()
|
||||
.enableCRC(true)
|
||||
.build(outputStream);
|
||||
publicKeys.encode(aOut);
|
||||
aOut.close();
|
||||
} else {
|
||||
publicKeys.encode(outputStream);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ExtractCert noArmor() {
|
||||
this.armor = false;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.pgpainless.bouncycastle.sop.operation;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import sop.Profile;
|
||||
import sop.operation.ListProfiles;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BCListProfiles implements ListProfiles {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Profile> subcommand(@NotNull String s) {
|
||||
return List.of();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.pgpainless.bouncycastle.sop.operation;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Version;
|
||||
|
||||
public class BCVersion implements Version {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getBackendVersion() {
|
||||
return "Bouncy Castle 1.79"; // TODO: Extract from pom
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Bouncy Castle SOP";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "1.0-SNAPSHOT"; // TODO: Extract from pom
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getExtendedVersion() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSopSpecRevisionNumber() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSopSpecImplementationIncomplete() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getSopSpecImplementationRemarks() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getSopVVersion() throws SOPGPException.UnsupportedOption {
|
||||
return "1.0";
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue