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

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.publicSigningKey = signingKey.getPublicKey();
this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey); this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey);
unhashedSubpackets = new SignatureSubpacketGeneratorWrapper(); unhashedSubpackets = SignatureSubpacketGeneratorWrapper.createEmptySubpackets();
hashedSubpackets = new SignatureSubpacketGeneratorWrapper(publicSigningKey); hashedSubpackets = SignatureSubpacketGeneratorWrapper.createHashedSubpackets(publicSigningKey);
} }
public AbstractSignatureBuilder(PGPSecretKey certificationKey, SecretKeyRingProtector protector, PGPSignature archetypeSignature) throws WrongPassphraseException { 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.publicSigningKey = certificationKey.getPublicKey();
this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey); this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey);
unhashedSubpackets = new SignatureSubpacketGeneratorWrapper(archetypeSignature.getUnhashedSubPackets()); unhashedSubpackets = SignatureSubpacketGeneratorWrapper.refreshUnhashedSubpackets(archetypeSignature);
hashedSubpackets = new SignatureSubpacketGeneratorWrapper(publicSigningKey, archetypeSignature.getHashedSubPackets()); hashedSubpackets = SignatureSubpacketGeneratorWrapper.refreshHashedSubpackets(publicSigningKey, archetypeSignature);
} }
protected HashAlgorithm negotiateHashAlgorithm(PGPPublicKey publicKey) { 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 class SubkeyBindingSignatureBuilder extends AbstractSignatureBuilder<SubkeyBindingSignatureBuilder> {
public SubkeyBindingSignatureBuilder(SignatureType signatureType, PGPSecretKey signingKey, SecretKeyRingProtector protector) throws WrongPassphraseException { public SubkeyBindingSignatureBuilder(PGPSecretKey signingKey, SecretKeyRingProtector protector)
super(signatureType, signingKey, protector); throws WrongPassphraseException {
super(SignatureType.SUBKEY_BINDING, signingKey, protector);
} }
@Override @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<>(); private final List<SignatureSubpacket> unsupportedSubpackets = new ArrayList<>();
public SignatureSubpacketGeneratorWrapper() { public SignatureSubpacketGeneratorWrapper() {
setSignatureCreationTime(new Date());
} }
public SignatureSubpacketGeneratorWrapper(PGPPublicKey issuer) { public static SignatureSubpacketGeneratorWrapper refreshHashedSubpackets(PGPPublicKey issuer, PGPSignature oldSignature) {
setSignatureCreationTime(new Date()); return createHashedSubpacketsFrom(issuer, oldSignature.getHashedSubPackets());
setIssuerFingerprintAndKeyId(issuer);
} }
public SignatureSubpacketGeneratorWrapper(PGPPublicKey issuer, PGPSignatureSubpacketVector base) { public static SignatureSubpacketGeneratorWrapper refreshUnhashedSubpackets(PGPSignature oldSignature) {
extractSubpacketsFromVector(base); return createSubpacketsFrom(oldSignature.getUnhashedSubPackets());
setSignatureCreationTime(new Date());
setIssuerFingerprintAndKeyId(issuer);
} }
public SignatureSubpacketGeneratorWrapper(PGPSignatureSubpacketVector base) { public static SignatureSubpacketGeneratorWrapper createHashedSubpacketsFrom(PGPPublicKey issuer, PGPSignatureSubpacketVector base) {
extractSubpacketsFromVector(base); SignatureSubpacketGeneratorWrapper wrapper = createSubpacketsFrom(base);
setSignatureCreationTime(new Date()); 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) { private void extractSubpacketsFromVector(PGPSignatureSubpacketVector base) {

View file

@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless; import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.EncryptionPurpose; import org.pgpainless.algorithm.EncryptionPurpose;
import org.pgpainless.algorithm.KeyFlag; import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.SignatureType;
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.util.Passphrase; import org.pgpainless.util.Passphrase;
@ -40,7 +39,7 @@ public class SubkeyBindingSignatureBuilderTest {
PGPPublicKey subkey = PGPainless.inspectKeyRing(tempSubkeyRing) PGPPublicKey subkey = PGPainless.inspectKeyRing(tempSubkeyRing)
.getEncryptionSubkeys(EncryptionPurpose.STORAGE_AND_COMMUNICATIONS).get(0); .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().addNotationData(false, "testnotation@pgpainless.org", "hello-world");
skbb.getHashedSubpackets().setKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE); skbb.getHashedSubpackets().setKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE);
PGPSignature binding = skbb.build(subkey); PGPSignature binding = skbb.build(subkey);

View file

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