mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-26 22:32:07 +01:00
Restructured API
This commit is contained in:
parent
b8a376f86a
commit
3438b7259a
6 changed files with 97 additions and 58 deletions
|
@ -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)
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue