More signature builder experimentations

This commit is contained in:
Paul Schaub 2021-10-25 21:03:34 +02:00
parent e9dc26b1da
commit de926e022f
8 changed files with 168 additions and 21 deletions

View File

@ -43,8 +43,8 @@ public abstract class AbstractSignatureBuilder<B extends AbstractSignatureBuilde
this.publicSigningKey = signingKey.getPublicKey();
this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey);
unhashedSubpackets = new SignatureSubpacketGeneratorWrapper();
hashedSubpackets = new SignatureSubpacketGeneratorWrapper(publicSigningKey);
unhashedSubpackets = SignatureSubpacketGeneratorWrapper.createEmptySubpackets();
hashedSubpackets = SignatureSubpacketGeneratorWrapper.createHashedSubpackets(publicSigningKey);
}
public AbstractSignatureBuilder(PGPSecretKey certificationKey, SecretKeyRingProtector protector, PGPSignature archetypeSignature) throws WrongPassphraseException {
@ -57,8 +57,8 @@ public abstract class AbstractSignatureBuilder<B extends AbstractSignatureBuilde
this.publicSigningKey = certificationKey.getPublicKey();
this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey);
unhashedSubpackets = new SignatureSubpacketGeneratorWrapper(archetypeSignature.getUnhashedSubPackets());
hashedSubpackets = new SignatureSubpacketGeneratorWrapper(publicSigningKey, archetypeSignature.getHashedSubPackets());
unhashedSubpackets = SignatureSubpacketGeneratorWrapper.refreshUnhashedSubpackets(archetypeSignature);
hashedSubpackets = SignatureSubpacketGeneratorWrapper.refreshHashedSubpackets(publicSigningKey, archetypeSignature);
}
protected HashAlgorithm negotiateHashAlgorithm(PGPPublicKey publicKey) {

View File

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.signature.builder;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.pgpainless.algorithm.SignatureType;
import org.pgpainless.exception.WrongPassphraseException;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
public class PrimaryKeyBindingSignatureBuilder extends AbstractSignatureBuilder<PrimaryKeyBindingSignatureBuilder> {
public PrimaryKeyBindingSignatureBuilder(PGPSecretKey subkey, SecretKeyRingProtector subkeyProtector)
throws WrongPassphraseException {
super(SignatureType.PRIMARYKEY_BINDING, subkey, subkeyProtector);
}
public SelfSignatureSubpackets getHashedSubpackets() {
return hashedSubpackets;
}
public SelfSignatureSubpackets getUnhashedSubpackets() {
return unhashedSubpackets;
}
@Override
protected boolean isValidSignatureType(SignatureType type) {
return type == SignatureType.PRIMARYKEY_BINDING;
}
public PGPSignature build(PGPPublicKey primaryKey) throws PGPException {
return buildAndInitSignatureGenerator()
.generateCertification(primaryKey, publicSigningKey);
}
}

View File

@ -0,0 +1,74 @@
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.signature.builder;
import java.io.IOException;
import javax.annotation.Nullable;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.signature.subpackets.BindingSignatureCallback;
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
public class SignatureBuilder {
public SubkeyBindingSignatureBuilder subkeyBindingSignatureBuilder(
PGPSecretKey primaryKey,
SecretKeyRingProtector primaryKeyProtector,
PGPSecretKey subkey,
SecretKeyRingProtector subkeyProtector,
@Nullable BindingSignatureCallback subkeyBindingSubpacketsCallback,
@Nullable BindingSignatureCallback primaryKeyBindingSubpacketsCallback,
KeyFlag... flags)
throws PGPException, IOException {
if (flags.length == 0) {
throw new IllegalArgumentException("Keyflags for subkey binding cannot be empty.");
}
SubkeyBindingSignatureBuilder subkeyBindingBuilder = new SubkeyBindingSignatureBuilder(primaryKey, primaryKeyProtector);
SelfSignatureSubpackets hashedSubpackets = subkeyBindingBuilder.getHashedSubpackets();
hashedSubpackets.setKeyFlags(flags);
boolean isSigningKey = false;
for (KeyFlag flag : flags) {
if (flag == KeyFlag.SIGN_DATA) {
isSigningKey = true;
break;
}
}
if (isSigningKey) {
PGPSignature backsig = primaryKeyBindingSignature(
subkey, subkeyProtector, primaryKey.getPublicKey(), primaryKeyBindingSubpacketsCallback);
hashedSubpackets.addEmbeddedSignature(backsig);
}
if (subkeyBindingSubpacketsCallback != null) {
subkeyBindingSubpacketsCallback.modifyHashedSubpackets(subkeyBindingBuilder.getHashedSubpackets());
subkeyBindingSubpacketsCallback.modifyUnhashedSubpackets(subkeyBindingBuilder.getUnhashedSubpackets());
}
return subkeyBindingBuilder;
}
public PGPSignature primaryKeyBindingSignature(
PGPSecretKey subkey,
SecretKeyRingProtector subkeyProtector,
PGPPublicKey primaryKey,
BindingSignatureCallback primaryKeyBindingSubpacketsCallback) throws PGPException {
PrimaryKeyBindingSignatureBuilder builder = new PrimaryKeyBindingSignatureBuilder(subkey, subkeyProtector);
if (primaryKeyBindingSubpacketsCallback != null) {
primaryKeyBindingSubpacketsCallback.modifyHashedSubpackets(builder.getHashedSubpackets());
primaryKeyBindingSubpacketsCallback.modifyUnhashedSubpackets(builder.getUnhashedSubpackets());
}
return builder.build(primaryKey);
}
}

View File

@ -15,8 +15,9 @@ import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
public class SubkeyBindingSignatureBuilder extends AbstractSignatureBuilder<SubkeyBindingSignatureBuilder> {
public SubkeyBindingSignatureBuilder(SignatureType signatureType, PGPSecretKey signingKey, SecretKeyRingProtector protector) throws WrongPassphraseException {
super(signatureType, signingKey, protector);
public SubkeyBindingSignatureBuilder(PGPSecretKey signingKey, SecretKeyRingProtector protector)
throws WrongPassphraseException {
super(SignatureType.SUBKEY_BINDING, signingKey, protector);
}
@Override

View File

@ -0,0 +1,12 @@
// 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

@ -75,23 +75,44 @@ public class SignatureSubpacketGeneratorWrapper
private final List<SignatureSubpacket> unsupportedSubpackets = new ArrayList<>();
public SignatureSubpacketGeneratorWrapper() {
setSignatureCreationTime(new Date());
}
public SignatureSubpacketGeneratorWrapper(PGPPublicKey issuer) {
setSignatureCreationTime(new Date());
setIssuerFingerprintAndKeyId(issuer);
public static SignatureSubpacketGeneratorWrapper refreshHashedSubpackets(PGPPublicKey issuer, PGPSignature oldSignature) {
return createHashedSubpacketsFrom(issuer, oldSignature.getHashedSubPackets());
}
public SignatureSubpacketGeneratorWrapper(PGPPublicKey issuer, PGPSignatureSubpacketVector base) {
extractSubpacketsFromVector(base);
setSignatureCreationTime(new Date());
setIssuerFingerprintAndKeyId(issuer);
public static SignatureSubpacketGeneratorWrapper refreshUnhashedSubpackets(PGPSignature oldSignature) {
return createSubpacketsFrom(oldSignature.getUnhashedSubPackets());
}
public SignatureSubpacketGeneratorWrapper(PGPSignatureSubpacketVector base) {
extractSubpacketsFromVector(base);
setSignatureCreationTime(new Date());
public static SignatureSubpacketGeneratorWrapper createHashedSubpacketsFrom(PGPPublicKey issuer, PGPSignatureSubpacketVector base) {
SignatureSubpacketGeneratorWrapper wrapper = createSubpacketsFrom(base);
wrapper.setIssuerFingerprintAndKeyId(issuer);
return wrapper;
}
public static SignatureSubpacketGeneratorWrapper createSubpacketsFrom(PGPSignatureSubpacketVector base) {
SignatureSubpacketGeneratorWrapper wrapper = new SignatureSubpacketGeneratorWrapper();
wrapper.extractSubpacketsFromVector(base);
wrapper.setSignatureCreationTime(new Date());
return wrapper;
}
public static SignatureSubpacketGeneratorWrapper createEmptySubpackets() {
return new SignatureSubpacketGeneratorWrapper();
}
public static SignatureSubpacketGeneratorWrapper createHashedSubpackets() {
SignatureSubpacketGeneratorWrapper wrapper = new SignatureSubpacketGeneratorWrapper();
wrapper.setSignatureCreationTime(new Date());
return wrapper;
}
public static SignatureSubpacketGeneratorWrapper createHashedSubpackets(PGPPublicKey issuer) {
SignatureSubpacketGeneratorWrapper wrapper = createHashedSubpackets();
wrapper.setIssuerFingerprintAndKeyId(issuer);
return wrapper;
}
private void extractSubpacketsFromVector(PGPSignatureSubpacketVector base) {

View File

@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.EncryptionPurpose;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.SignatureType;
import org.pgpainless.key.info.KeyRingInfo;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.util.Passphrase;
@ -40,7 +39,7 @@ public class SubkeyBindingSignatureBuilderTest {
PGPPublicKey subkey = PGPainless.inspectKeyRing(tempSubkeyRing)
.getEncryptionSubkeys(EncryptionPurpose.STORAGE_AND_COMMUNICATIONS).get(0);
SubkeyBindingSignatureBuilder skbb = new SubkeyBindingSignatureBuilder(SignatureType.SUBKEY_BINDING, secretKey.getSecretKey(), protector);
SubkeyBindingSignatureBuilder skbb = new SubkeyBindingSignatureBuilder(secretKey.getSecretKey(), protector);
skbb.getHashedSubpackets().addNotationData(false, "testnotation@pgpainless.org", "hello-world");
skbb.getHashedSubpackets().setKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE);
PGPSignature binding = skbb.build(subkey);

View File

@ -69,13 +69,13 @@ public class SignatureSubpacketGeneratorWrapperTest {
@BeforeEach
public void createWrapper() {
wrapper = new SignatureSubpacketGeneratorWrapper(key);
wrapper = SignatureSubpacketGeneratorWrapper.createHashedSubpackets(key);
}
@Test
public void initialStateTest() {
Date now = new Date();
wrapper = new SignatureSubpacketGeneratorWrapper();
wrapper = SignatureSubpacketGeneratorWrapper.createHashedSubpackets();
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
assertEquals(now.getTime(), vector.getSignatureCreationTime().getTime(), 1000);