mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-23 11:27:57 +01:00
More signature builder experimentations
This commit is contained in:
parent
e9dc26b1da
commit
de926e022f
8 changed files with 168 additions and 21 deletions
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue