Compare commits
6 Commits
89038ebedf
...
8066650584
Author | SHA1 | Date |
---|---|---|
Paul Schaub | 8066650584 | |
Paul Schaub | bd1949871a | |
Paul Schaub | 194e4e1458 | |
Paul Schaub | 44be5aa981 | |
Paul Schaub | 3ac273757a | |
Paul Schaub | fa5bdfcd82 |
|
@ -14,9 +14,12 @@ SPDX-License-Identifier: CC0-1.0
|
|||
- Rewrote most of the codebase in Kotlin
|
||||
- Removed `OpenPgpMetadata` (`decryptionStream.getResult()`) in favor of `MessageMetadata` (`decryptionStream.getMetadata()`)
|
||||
- `pgpainless-sop`, `pgpainless-cli`
|
||||
- Bump `sop-java` to `8.0.1`, implementing [SOP Spec Revision 08](https://www.ietf.org/archive/id/draft-dkg-openpgp-stateless-cli-08.html)
|
||||
- Bump `sop-java` to `10.0.0`, implementing [SOP Spec Revision 10](https://www.ietf.org/archive/id/draft-dkg-openpgp-stateless-cli-10.html)
|
||||
- Change API of `sop.encrypt` to return a `ReadyWithResult<EncryptionResult>` to expose the session key
|
||||
- `decrypt --verify-with`: Fix to not throw `NoSignature` exception (exit code 3) if `VERIFICATIONS` is empty
|
||||
- Separate signature verification operations into `SOPV` interface
|
||||
- Add `version --sopv` option
|
||||
- Throw `BadData` error when passing KEYS where CERTS are expected.
|
||||
- Properly feed EOS tokens to the pushdown automaton when reaching the end of stream (thanks @iNPUTmice)
|
||||
- Do not choke on unknown signature subpackets (thanks @Jerbell)
|
||||
- Prevent timing issues resuting in subkey binding signatures predating the subkey (@thanks Jerbell)
|
||||
|
|
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: Apache-2.0
|
|||
|
||||
# PGPainless-SOP
|
||||
|
||||
[![Spec Revision: 8](https://img.shields.io/badge/Spec%20Revision-8-blue)](https://datatracker.ietf.org/doc/draft-dkg-openpgp-stateless-cli/)
|
||||
[![Spec Revision: 10](https://img.shields.io/badge/Spec%20Revision-10-blue)](https://datatracker.ietf.org/doc/draft-dkg-openpgp-stateless-cli/)
|
||||
[![Maven Central](https://badgen.net/maven/v/maven-central/org.pgpainless/pgpainless-sop)](https://search.maven.org/artifact/org.pgpainless/pgpainless-sop)
|
||||
[![javadoc](https://javadoc.io/badge2/org.pgpainless/pgpainless-sop/javadoc.svg)](https://javadoc.io/doc/org.pgpainless/pgpainless-sop)
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@ package org.pgpainless.sop;
|
|||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||
import org.bouncycastle.openpgp.PGPRuntimeOperationException;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.key.collection.PGPKeyRingCollection;
|
||||
import sop.exception.SOPGPException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -44,19 +46,24 @@ class KeyReader {
|
|||
|
||||
static PGPPublicKeyRingCollection readPublicKeys(InputStream certIn, boolean requireContent)
|
||||
throws IOException {
|
||||
PGPPublicKeyRingCollection certs;
|
||||
PGPKeyRingCollection certs;
|
||||
try {
|
||||
certs = PGPainless.readKeyRing().publicKeyRingCollection(certIn);
|
||||
certs = PGPainless.readKeyRing().keyRingCollection(certIn, false);
|
||||
} catch (IOException e) {
|
||||
String msg = e.getMessage();
|
||||
if (msg != null && (msg.startsWith("unknown object in stream:") || msg.startsWith("invalid header encountered"))) {
|
||||
throw new SOPGPException.BadData(e);
|
||||
}
|
||||
throw e;
|
||||
} catch (PGPRuntimeOperationException e) {
|
||||
throw new SOPGPException.BadData(e);
|
||||
}
|
||||
if (requireContent && certs.size() == 0) {
|
||||
if (certs.getPgpSecretKeyRingCollection().size() != 0) {
|
||||
throw new SOPGPException.BadData("Secret key components encountered, while certificates were expected.");
|
||||
}
|
||||
if (requireContent && certs.getPgpPublicKeyRingCollection().size() == 0) {
|
||||
throw new SOPGPException.BadData(new PGPException("No cert data found."));
|
||||
}
|
||||
return certs;
|
||||
return certs.getPgpPublicKeyRingCollection();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package org.pgpainless.sop;
|
|||
|
||||
import org.pgpainless.util.ArmoredOutputStreamFactory;
|
||||
import sop.SOP;
|
||||
import sop.SOPV;
|
||||
import sop.operation.Armor;
|
||||
import sop.operation.ChangeKeyPassword;
|
||||
import sop.operation.Dearmor;
|
||||
|
@ -29,6 +30,8 @@ import javax.annotation.Nonnull;
|
|||
* <pre> {@code
|
||||
* SOP sop = new SOPImpl();
|
||||
* }</pre>
|
||||
*
|
||||
* For a slimmed down interface that merely focuses on signature verification, see {@link SOPVImpl}.
|
||||
*/
|
||||
public class SOPImpl implements SOP {
|
||||
|
||||
|
@ -36,10 +39,14 @@ public class SOPImpl implements SOP {
|
|||
ArmoredOutputStreamFactory.setVersionInfo(null);
|
||||
}
|
||||
|
||||
// Delegate for sig verification operations
|
||||
private final SOPV sopv = new SOPVImpl();
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Version version() {
|
||||
return new VersionImpl();
|
||||
// Delegate to SOPV
|
||||
return sopv.version();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,13 +88,15 @@ public class SOPImpl implements SOP {
|
|||
@Override
|
||||
@Nonnull
|
||||
public DetachedVerify detachedVerify() {
|
||||
return new DetachedVerifyImpl();
|
||||
// Delegate to SOPV
|
||||
return sopv.detachedVerify();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public InlineVerify inlineVerify() {
|
||||
return new InlineVerifyImpl();
|
||||
// Delegate to SOPV
|
||||
return sopv.inlineVerify();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.sop;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.pgpainless.util.ArmoredOutputStreamFactory;
|
||||
import sop.SOPV;
|
||||
import sop.operation.DetachedVerify;
|
||||
import sop.operation.InlineVerify;
|
||||
import sop.operation.Version;
|
||||
|
||||
/**
|
||||
* Implementation of the <pre>sopv</pre> interface subset using PGPainless.
|
||||
*/
|
||||
public class SOPVImpl implements SOPV {
|
||||
|
||||
static {
|
||||
ArmoredOutputStreamFactory.setVersionInfo(null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DetachedVerify detachedVerify() {
|
||||
return new DetachedVerifyImpl();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public InlineVerify inlineVerify() {
|
||||
return new InlineVerifyImpl();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Version version() {
|
||||
return new VersionImpl();
|
||||
}
|
||||
}
|
|
@ -10,6 +10,8 @@ import java.util.Locale;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Version;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -20,7 +22,9 @@ import javax.annotation.Nonnull;
|
|||
public class VersionImpl implements Version {
|
||||
|
||||
// draft version
|
||||
private static final int SOP_VERSION = 8;
|
||||
private static final int SOP_VERSION = 10;
|
||||
|
||||
private static final String SOPV_VERSION = "1.0";
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
|
@ -86,4 +90,9 @@ public class VersionImpl implements Version {
|
|||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getSopVVersion() throws SOPGPException.UnsupportedOption {
|
||||
return SOPV_VERSION;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,4 +72,11 @@ public class VersionTest {
|
|||
assertTrue(fullSopSpecVersion.endsWith(incompletenessRemarks));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSopVVersion() {
|
||||
String sopVVersion = sop.version().getSopVVersion();
|
||||
assertNotNull(sopVVersion);
|
||||
assertTrue(sopVVersion.matches("\\d+\\.\\d+(\\.\\d+)*")); // X.Y or X.Y.Z... etc.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,6 @@ allprojects {
|
|||
logbackVersion = '1.2.13'
|
||||
mockitoVersion = '4.5.1'
|
||||
slf4jVersion = '1.7.36'
|
||||
sopJavaVersion = '8.0.1'
|
||||
sopJavaVersion = '10.0.0'
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue