1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-23 04:42:06 +01:00

Restructured API

This commit is contained in:
Paul Schaub 2021-11-03 13:24:05 +01:00
parent b8a376f86a
commit 3438b7259a
6 changed files with 97 additions and 58 deletions

View file

@ -14,36 +14,60 @@ import org.bouncycastle.openpgp.PGPSignature;
import org.pgpainless.algorithm.KeyFlag; import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.exception.WrongPassphraseException; import org.pgpainless.exception.WrongPassphraseException;
import org.pgpainless.key.protection.SecretKeyRingProtector; import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.signature.subpackets.BindingSignatureCallback;
import org.pgpainless.signature.subpackets.SelfSignatureCallback;
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets; import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
public class SignatureBuilder { public final class SignatureBuilder {
public SubkeyBindingSignatureBuilder bindSubkey( private SignatureBuilder() {
}
public static SubkeyBindingSignatureBuilder bindNonSigningSubkey(
PGPSecretKey primaryKey,
SecretKeyRingProtector primaryKeyProtector,
@Nullable SelfSignatureSubpackets.Callback subkeyBindingSubpacketsCallback,
KeyFlag... flags) throws WrongPassphraseException {
if (hasSignDataFlag(flags)) {
throw new IllegalArgumentException("Binding a subkey with SIGN_DATA flag requires primary key backsig." +
"Please use the method bindSigningSubkey().");
}
return bindSubkey(primaryKey, primaryKeyProtector, subkeyBindingSubpacketsCallback, flags);
}
public static SubkeyBindingSignatureBuilder bindSigningSubkey(
PGPSecretKey primaryKey, PGPSecretKey primaryKey,
SecretKeyRingProtector primaryKeyProtector, SecretKeyRingProtector primaryKeyProtector,
PGPSecretKey subkey, PGPSecretKey subkey,
SecretKeyRingProtector subkeyProtector, SecretKeyRingProtector subkeyProtector,
@Nullable BindingSignatureCallback subkeyBindingSubpacketsCallback, @Nullable SelfSignatureSubpackets.Callback subkeyBindingSubpacketsCallback,
@Nullable BindingSignatureCallback primaryKeyBindingSubpacketsCallback, @Nullable SelfSignatureSubpackets.Callback primaryKeyBindingSubpacketsCallback,
KeyFlag... flags) KeyFlag... flags)
throws PGPException, IOException { throws PGPException, IOException {
if (flags.length == 0) {
throw new IllegalArgumentException("Keyflags for subkey binding cannot be empty.");
}
SubkeyBindingSignatureBuilder subkeyBinder = new SubkeyBindingSignatureBuilder(primaryKey, primaryKeyProtector);
SelfSignatureSubpackets hashedSubpackets = subkeyBinder.getHashedSubpackets(); SubkeyBindingSignatureBuilder subkeyBinder = bindSubkey(primaryKey, primaryKeyProtector, subkeyBindingSubpacketsCallback, flags);
SelfSignatureSubpackets unhashedSubpackets = subkeyBinder.getUnhashedSubpackets();
hashedSubpackets.setKeyFlags(flags);
if (hasSignDataFlag(flags)) { if (hasSignDataFlag(flags)) {
PGPSignature backsig = createPrimaryKeyBinding( PGPSignature backsig = createPrimaryKeyBinding(
subkey, subkeyProtector, primaryKeyBindingSubpacketsCallback, primaryKey.getPublicKey()); subkey, subkeyProtector, primaryKeyBindingSubpacketsCallback, primaryKey.getPublicKey());
hashedSubpackets.addEmbeddedSignature(backsig); subkeyBinder.getHashedSubpackets().addEmbeddedSignature(backsig);
} }
return subkeyBinder;
}
private static SubkeyBindingSignatureBuilder bindSubkey(PGPSecretKey primaryKey,
SecretKeyRingProtector primaryKeyProtector,
@Nullable SelfSignatureSubpackets.Callback subkeyBindingSubpacketsCallback,
KeyFlag... flags) throws WrongPassphraseException {
if (flags.length == 0) {
throw new IllegalArgumentException("Keyflags for subkey binding cannot be empty.");
}
SubkeyBindingSignatureBuilder subkeyBinder = new SubkeyBindingSignatureBuilder(primaryKey, primaryKeyProtector);
SelfSignatureSubpackets hashedSubpackets = subkeyBinder.getHashedSubpackets();
SelfSignatureSubpackets unhashedSubpackets = subkeyBinder.getUnhashedSubpackets();
hashedSubpackets.setKeyFlags(flags);
if (subkeyBindingSubpacketsCallback != null) { if (subkeyBindingSubpacketsCallback != null) {
subkeyBindingSubpacketsCallback.modifyHashedSubpackets(hashedSubpackets); subkeyBindingSubpacketsCallback.modifyHashedSubpackets(hashedSubpackets);
subkeyBindingSubpacketsCallback.modifyUnhashedSubpackets(unhashedSubpackets); subkeyBindingSubpacketsCallback.modifyUnhashedSubpackets(unhashedSubpackets);
@ -52,10 +76,10 @@ public class SignatureBuilder {
return subkeyBinder; return subkeyBinder;
} }
public PrimaryKeyBindingSignatureBuilder bindPrimaryKey( public static PrimaryKeyBindingSignatureBuilder bindPrimaryKey(
PGPSecretKey subkey, PGPSecretKey subkey,
SecretKeyRingProtector subkeyProtector, SecretKeyRingProtector subkeyProtector,
@Nullable BindingSignatureCallback primaryKeyBindingSubpacketsCallback) throws WrongPassphraseException { @Nullable SelfSignatureSubpackets.Callback primaryKeyBindingSubpacketsCallback) throws WrongPassphraseException {
PrimaryKeyBindingSignatureBuilder primaryKeyBinder = new PrimaryKeyBindingSignatureBuilder(subkey, subkeyProtector); PrimaryKeyBindingSignatureBuilder primaryKeyBinder = new PrimaryKeyBindingSignatureBuilder(subkey, subkeyProtector);
if (primaryKeyBindingSubpacketsCallback != null) { if (primaryKeyBindingSubpacketsCallback != null) {
@ -66,20 +90,20 @@ public class SignatureBuilder {
return primaryKeyBinder; return primaryKeyBinder;
} }
public PGPSignature createPrimaryKeyBinding( public static PGPSignature createPrimaryKeyBinding(
PGPSecretKey subkey, PGPSecretKey subkey,
SecretKeyRingProtector subkeyProtector, SecretKeyRingProtector subkeyProtector,
@Nullable BindingSignatureCallback primaryKeyBindingSubpacketsCallback, @Nullable SelfSignatureSubpackets.Callback primaryKeyBindingSubpacketsCallback,
PGPPublicKey primaryKey) PGPPublicKey primaryKey)
throws PGPException { throws PGPException {
return bindPrimaryKey(subkey, subkeyProtector, primaryKeyBindingSubpacketsCallback) return bindPrimaryKey(subkey, subkeyProtector, primaryKeyBindingSubpacketsCallback)
.build(primaryKey); .build(primaryKey);
} }
public CertificationSignatureBuilder selfCertifyUserId( public static CertificationSignatureBuilder selfCertifyUserId(
PGPSecretKey primaryKey, PGPSecretKey primaryKey,
SecretKeyRingProtector primaryKeyProtector, SecretKeyRingProtector primaryKeyProtector,
@Nullable SelfSignatureCallback selfSignatureCallback, @Nullable SelfSignatureSubpackets.Callback selfSignatureCallback,
KeyFlag... flags) throws WrongPassphraseException { KeyFlag... flags) throws WrongPassphraseException {
CertificationSignatureBuilder certifier = new CertificationSignatureBuilder(primaryKey, primaryKeyProtector); CertificationSignatureBuilder certifier = new CertificationSignatureBuilder(primaryKey, primaryKeyProtector);
@ -91,10 +115,10 @@ public class SignatureBuilder {
return certifier; return certifier;
} }
public CertificationSignatureBuilder renewSelfCertification( public static CertificationSignatureBuilder renewSelfCertification(
PGPSecretKey primaryKey, PGPSecretKey primaryKey,
SecretKeyRingProtector primaryKeyProtector, SecretKeyRingProtector primaryKeyProtector,
@Nullable SelfSignatureCallback selfSignatureCallback, @Nullable SelfSignatureSubpackets.Callback selfSignatureCallback,
PGPSignature oldCertification) throws WrongPassphraseException { PGPSignature oldCertification) throws WrongPassphraseException {
CertificationSignatureBuilder certifier = CertificationSignatureBuilder certifier =
new CertificationSignatureBuilder(primaryKey, primaryKeyProtector, oldCertification); new CertificationSignatureBuilder(primaryKey, primaryKeyProtector, oldCertification);
@ -103,11 +127,11 @@ public class SignatureBuilder {
return null; return null;
} }
public PGPSignature createUserIdSelfCertification( public static PGPSignature createUserIdSelfCertification(
String userId, String userId,
PGPSecretKey primaryKey, PGPSecretKey primaryKey,
SecretKeyRingProtector primaryKeyProtector, SecretKeyRingProtector primaryKeyProtector,
@Nullable SelfSignatureCallback selfSignatureCallback, @Nullable SelfSignatureSubpackets.Callback selfSignatureCallback,
KeyFlag... flags) KeyFlag... flags)
throws PGPException { throws PGPException {
return selfCertifyUserId(primaryKey, primaryKeyProtector, selfSignatureCallback, flags) return selfCertifyUserId(primaryKey, primaryKeyProtector, selfSignatureCallback, flags)

View file

@ -1,12 +0,0 @@
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.signature.subpackets;
public interface BindingSignatureCallback {
void modifyHashedSubpackets(SelfSignatureSubpackets subpackets);
void modifyUnhashedSubpackets(SelfSignatureSubpackets subpackets);
}

View file

@ -12,6 +12,16 @@ import org.pgpainless.key.util.RevocationAttributes;
public interface RevocationSignatureSubpackets extends BaseSignatureSubpackets { public interface RevocationSignatureSubpackets extends BaseSignatureSubpackets {
interface Callback {
default void modifyHashedSubpackets(RevocationSignatureSubpackets subpackets) {
}
default void modifyUnhashedSubpackets(RevocationSignatureSubpackets subpackets) {
}
}
SignatureSubpacketGeneratorWrapper setRevocationReason(RevocationAttributes revocationAttributes); SignatureSubpacketGeneratorWrapper setRevocationReason(RevocationAttributes revocationAttributes);
SignatureSubpacketGeneratorWrapper setRevocationReason(boolean isCritical, RevocationAttributes revocationAttributes); SignatureSubpacketGeneratorWrapper setRevocationReason(boolean isCritical, RevocationAttributes revocationAttributes);

View file

@ -1,13 +0,0 @@
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.signature.subpackets;
public interface SelfSignatureCallback {
void modifyHashedSubpackets(SelfSignatureSubpackets subpackets);
void modifyUnhashedSubpackets(SelfSignatureSubpackets subpackets);
}

View file

@ -24,6 +24,16 @@ import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
public interface SelfSignatureSubpackets extends BaseSignatureSubpackets { public interface SelfSignatureSubpackets extends BaseSignatureSubpackets {
interface Callback {
default void modifyHashedSubpackets(SelfSignatureSubpackets subpackets) {
}
default void modifyUnhashedSubpackets(SelfSignatureSubpackets subpackets) {
}
}
SignatureSubpacketGeneratorWrapper setKeyFlags(KeyFlag... keyFlags); SignatureSubpacketGeneratorWrapper setKeyFlags(KeyFlag... keyFlags);
SignatureSubpacketGeneratorWrapper setKeyFlags(boolean isCritical, KeyFlag... keyFlags); SignatureSubpacketGeneratorWrapper setKeyFlags(boolean isCritical, KeyFlag... keyFlags);

View file

@ -5,12 +5,15 @@
package org.pgpainless.signature.builder; package org.pgpainless.signature.builder;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.IOException; import java.io.IOException;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.bouncycastle.bcpg.sig.NotationData;
import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKey;
@ -22,6 +25,8 @@ import org.pgpainless.algorithm.EncryptionPurpose;
import org.pgpainless.algorithm.KeyFlag; import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.key.info.KeyRingInfo; import org.pgpainless.key.info.KeyRingInfo;
import org.pgpainless.key.protection.SecretKeyRingProtector; import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
import org.pgpainless.util.Passphrase; import org.pgpainless.util.Passphrase;
public class SubkeyBindingSignatureBuilderTest { public class SubkeyBindingSignatureBuilderTest {
@ -36,20 +41,35 @@ public class SubkeyBindingSignatureBuilderTest {
PGPSecretKeyRing tempSubkeyRing = PGPainless.generateKeyRing() PGPSecretKeyRing tempSubkeyRing = PGPainless.generateKeyRing()
.modernKeyRing("Subkeys", null); .modernKeyRing("Subkeys", null);
PGPPublicKey subkey = PGPainless.inspectKeyRing(tempSubkeyRing) PGPPublicKey subkeyPub = PGPainless.inspectKeyRing(tempSubkeyRing)
.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0); .getEncryptionSubkeys(EncryptionPurpose.ANY).get(0);
PGPSecretKey subkeySec = tempSubkeyRing.getSecretKey(subkeyPub.getKeyID());
SubkeyBindingSignatureBuilder skbb = new SubkeyBindingSignatureBuilder(secretKey.getSecretKey(), protector); PGPSignature binding = SignatureBuilder.bindNonSigningSubkey(
skbb.getHashedSubpackets().addNotationData(false, "testnotation@pgpainless.org", "hello-world"); secretKey.getSecretKey(), protector,
skbb.getHashedSubpackets().setKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE); new SelfSignatureSubpackets.Callback() {
PGPSignature binding = skbb.build(subkey); @Override
subkey = PGPPublicKey.addCertification(subkey, binding); public void modifyHashedSubpackets(SelfSignatureSubpackets subpackets) {
PGPSecretKey secSubkey = tempSubkeyRing.getSecretKey(subkey.getKeyID()); subpackets.addNotationData(false, "testnotation@pgpainless.org", "hello-world");
secSubkey = PGPSecretKey.replacePublicKey(secSubkey, subkey); }
secretKey = PGPSecretKeyRing.insertSecretKey(secretKey, secSubkey); }, KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
.build(subkeyPub);
subkeyPub = PGPPublicKey.addCertification(subkeyPub, binding);
subkeySec = PGPSecretKey.replacePublicKey(subkeySec, subkeyPub);
secretKey = PGPSecretKeyRing.insertSecretKey(secretKey, subkeySec);
info = PGPainless.inspectKeyRing(secretKey); info = PGPainless.inspectKeyRing(secretKey);
List<PGPPublicKey> nextSubkeys = info.getEncryptionSubkeys(EncryptionPurpose.ANY); List<PGPPublicKey> nextSubkeys = info.getEncryptionSubkeys(EncryptionPurpose.ANY);
assertEquals(previousSubkeys.size() + 1, nextSubkeys.size()); assertEquals(previousSubkeys.size() + 1, nextSubkeys.size());
subkeyPub = secretKey.getPublicKey(subkeyPub.getKeyID());
Iterator<PGPSignature> newBindingSigs = subkeyPub.getSignaturesForKeyID(secretKey.getPublicKey().getKeyID());
PGPSignature bindingSig = newBindingSigs.next();
assertNotNull(bindingSig);
List<NotationData> notations = SignatureSubpacketsUtil.getHashedNotationData(bindingSig);
assertEquals(1, notations.size());
assertEquals("testnotation@pgpainless.org", notations.get(0).getNotationName());
assertEquals("hello-world", notations.get(0).getNotationValue());
} }
} }