mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-01-10 20:27:58 +01:00
Wip
This commit is contained in:
parent
25c95804ce
commit
176574df50
10 changed files with 238 additions and 374 deletions
|
@ -42,7 +42,6 @@ import org.pgpainless.algorithm.SignatureType;
|
|||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||
import org.pgpainless.implementation.ImplementationFactory;
|
||||
import org.pgpainless.key.generation.type.KeyType;
|
||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||
import org.pgpainless.provider.ProviderFactory;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpackets;
|
||||
|
@ -133,6 +132,8 @@ public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
|||
PGPKeyPair certKey = generateKeyPair(primaryKeySpec);
|
||||
PGPContentSignerBuilder signer = buildContentSigner(certKey);
|
||||
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(signer);
|
||||
|
||||
// Prepare primary user-id sig
|
||||
SignatureSubpackets hashedSubPacketGenerator = primaryKeySpec.getSubpacketGenerator();
|
||||
hashedSubPacketGenerator.setPrimaryUserId();
|
||||
if (expirationDate != null) {
|
||||
|
@ -142,9 +143,7 @@ public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
|||
SignatureSubpacketsHelper.applyTo(hashedSubPacketGenerator, generator);
|
||||
PGPSignatureSubpacketVector hashedSubPackets = generator.generate();
|
||||
|
||||
// Generator which the user can get the key pair from
|
||||
PGPKeyRingGenerator ringGenerator = buildRingGenerator(certKey, signer, keyFingerprintCalculator, hashedSubPackets, secretKeyEncryptor);
|
||||
|
||||
addSubKeys(certKey, ringGenerator);
|
||||
|
||||
// Generate secret key ring with only primary user id
|
||||
|
@ -155,10 +154,10 @@ public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
|||
// Attempt to add additional user-ids to the primary public key
|
||||
PGPPublicKey primaryPubKey = secretKeys.next().getPublicKey();
|
||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKeyRing.getSecretKey(), secretKeyDecryptor);
|
||||
Iterator<String> additionalUserIds = userIds.iterator();
|
||||
additionalUserIds.next(); // Skip primary user id
|
||||
while (additionalUserIds.hasNext()) {
|
||||
String additionalUserId = additionalUserIds.next();
|
||||
Iterator<String> userIdIterator = this.userIds.iterator();
|
||||
userIdIterator.next(); // Skip primary user id
|
||||
while (userIdIterator.hasNext()) {
|
||||
String additionalUserId = userIdIterator.next();
|
||||
signatureGenerator.init(SignatureType.POSITIVE_CERTIFICATION.getCode(), privateKey);
|
||||
PGPSignature additionalUserIdSignature =
|
||||
signatureGenerator.generateCertification(additionalUserId, primaryPubKey);
|
||||
|
@ -175,7 +174,6 @@ public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
|||
secretKeyList.add(secretKeys.next());
|
||||
}
|
||||
secretKeyRing = new PGPSecretKeyRing(secretKeyList);
|
||||
|
||||
return secretKeyRing;
|
||||
}
|
||||
|
||||
|
@ -266,31 +264,4 @@ public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
|||
PGPKeyPair pgpKeyPair = ImplementationFactory.getInstance().getPGPKeyPair(type.getAlgorithm(), keyPair, new Date());
|
||||
return pgpKeyPair;
|
||||
}
|
||||
|
||||
private static SecretKeyRingProtector protectorFromPassphrase(@Nonnull Passphrase passphrase, long keyId) {
|
||||
if (!passphrase.isValid()) {
|
||||
throw new IllegalStateException("Passphrase has been cleared.");
|
||||
}
|
||||
if (passphrase.isEmpty()) {
|
||||
return SecretKeyRingProtector.unprotectedKeys();
|
||||
} else {
|
||||
return SecretKeyRingProtector.unlockSingleKeyWith(passphrase, keyId);
|
||||
}
|
||||
}
|
||||
|
||||
public static PGPSecretKey generatePGPSecretKey(KeySpec keySpec, @Nonnull Passphrase passphrase, boolean isPrimary)
|
||||
throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
||||
PGPDigestCalculator keyFingerprintCalculator = ImplementationFactory.getInstance()
|
||||
.getV4FingerprintCalculator();
|
||||
PGPKeyPair keyPair = generateKeyPair(keySpec);
|
||||
|
||||
SecretKeyRingProtector protector = protectorFromPassphrase(passphrase, keyPair.getKeyID());
|
||||
|
||||
return new PGPSecretKey(
|
||||
keyPair.getPrivateKey(),
|
||||
keyPair.getPublicKey(),
|
||||
keyFingerprintCalculator,
|
||||
isPrimary,
|
||||
protector.getEncryptor(keyPair.getKeyID()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public class KeySpec {
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
SignatureSubpackets getSubpacketGenerator() {
|
||||
public SignatureSubpackets getSubpacketGenerator() {
|
||||
return subpacketGenerator;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.bouncycastle.openpgp.PGPKeyPair;
|
|||
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
|
||||
import org.bouncycastle.openpgp.PGPPrivateKey;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
|
@ -36,11 +35,12 @@ import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
|||
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
|
||||
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder;
|
||||
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.algorithm.HashAlgorithm;
|
||||
import org.pgpainless.algorithm.KeyFlag;
|
||||
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||
import org.pgpainless.algorithm.SignatureType;
|
||||
import org.pgpainless.algorithm.negotiation.HashAlgorithmNegotiator;
|
||||
import org.pgpainless.implementation.ImplementationFactory;
|
||||
import org.pgpainless.key.OpenPgpFingerprint;
|
||||
import org.pgpainless.key.generation.KeyRingBuilder;
|
||||
|
@ -57,14 +57,14 @@ import org.pgpainless.key.protection.passphrase_provider.SolitaryPassphraseProvi
|
|||
import org.pgpainless.key.util.KeyRingUtils;
|
||||
import org.pgpainless.key.util.RevocationAttributes;
|
||||
import org.pgpainless.signature.SignatureUtils;
|
||||
import org.pgpainless.signature.builder.PrimaryKeyBindingSignatureBuilder;
|
||||
import org.pgpainless.signature.builder.RevocationSignatureBuilder;
|
||||
import org.pgpainless.signature.builder.SelfSignatureBuilder;
|
||||
import org.pgpainless.signature.builder.SignatureFactory;
|
||||
import org.pgpainless.signature.builder.SubkeyBindingSignatureBuilder;
|
||||
import org.pgpainless.signature.subpackets.RevocationSignatureSubpackets;
|
||||
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorUtil;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpackets;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsHelper;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||
import org.pgpainless.util.CollectionUtils;
|
||||
import org.pgpainless.util.Passphrase;
|
||||
|
@ -95,33 +95,21 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
|||
SecretKeyRingProtector protector) throws PGPException {
|
||||
userId = sanitizeUserId(userId);
|
||||
|
||||
List<PGPSecretKey> secretKeyList = new ArrayList<>();
|
||||
Iterator<PGPSecretKey> secretKeyIterator = secretKeyRing.getSecretKeys();
|
||||
// user-id certifications live on the primary key
|
||||
PGPSecretKey primaryKey = secretKeyRing.getSecretKey();
|
||||
|
||||
// add user-id certificate to primary key
|
||||
PGPSecretKey primaryKey = secretKeyIterator.next();
|
||||
PGPPublicKey publicKey = primaryKey.getPublicKey();
|
||||
// retain key flags from previous signature
|
||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeyRing);
|
||||
List<KeyFlag> keyFlags = info.getKeyFlagsOf(info.getKeyId());
|
||||
|
||||
SelfSignatureBuilder builder = SignatureFactory.selfCertifyUserId(
|
||||
primaryKey,
|
||||
protector,
|
||||
signatureSubpacketCallback,
|
||||
keyFlags.toArray(new KeyFlag[0]));
|
||||
keyFlags);
|
||||
builder.setSignatureType(SignatureType.POSITIVE_CERTIFICATION);
|
||||
builder.applyCallback(signatureSubpacketCallback);
|
||||
PGPSignature signature = builder.build(publicKey, userId);
|
||||
|
||||
publicKey = PGPPublicKey.addCertification(publicKey,
|
||||
userId, signature);
|
||||
primaryKey = PGPSecretKey.replacePublicKey(primaryKey, publicKey);
|
||||
secretKeyList.add(primaryKey);
|
||||
|
||||
while (secretKeyIterator.hasNext()) {
|
||||
secretKeyList.add(secretKeyIterator.next());
|
||||
}
|
||||
|
||||
secretKeyRing = new PGPSecretKeyRing(secretKeyList);
|
||||
PGPSignature signature = builder.build(primaryKey.getPublicKey(), userId);
|
||||
secretKeyRing = KeyRingUtils.injectCertification(secretKeyRing, userId, signature);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -138,51 +126,30 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
|||
public SecretKeyRingEditorInterface addSubKey(@Nonnull KeySpec keySpec,
|
||||
@Nonnull Passphrase subKeyPassphrase,
|
||||
SecretKeyRingProtector secretKeyRingProtector)
|
||||
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
|
||||
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, IOException {
|
||||
|
||||
PGPKeyPair keyPair = KeyRingBuilder.generateKeyPair(keySpec);
|
||||
|
||||
PGPSecretKey secretSubKey = generateSubKey(keySpec, subKeyPassphrase);
|
||||
SecretKeyRingProtector subKeyProtector = PasswordBasedSecretKeyRingProtector
|
||||
.forKey(secretSubKey, subKeyPassphrase);
|
||||
PGPSignatureSubpacketVector hashedSubpackets = keySpec.getSubpackets();
|
||||
PGPSignatureSubpacketVector unhashedSubpackets = null;
|
||||
.forKeyId(keyPair.getKeyID(), subKeyPassphrase);
|
||||
|
||||
return addSubKey(secretSubKey, hashedSubpackets, unhashedSubpackets, subKeyProtector, secretKeyRingProtector);
|
||||
SelfSignatureSubpackets.Callback callback = new SelfSignatureSubpackets.Callback() {
|
||||
@Override
|
||||
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
||||
SignatureSubpacketsHelper.applyFrom(keySpec.getSubpackets(), (SignatureSubpackets) hashedSubpackets);
|
||||
}
|
||||
};
|
||||
|
||||
List<KeyFlag> keyFlags = KeyFlag.fromBitmask(keySpec.getSubpackets().getKeyFlags());
|
||||
KeyFlag firstFlag = keyFlags.remove(0);
|
||||
KeyFlag[] otherFlags = keyFlags.toArray(new KeyFlag[0]);
|
||||
|
||||
return addSubKey(keyPair, callback, subKeyProtector, secretKeyRingProtector, firstFlag, otherFlags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public SecretKeyRingEditorInterface addSubKey(PGPSecretKey secretSubKey,
|
||||
PGPSignatureSubpacketVector hashedSubpackets,
|
||||
PGPSignatureSubpacketVector unhashedSubpackets,
|
||||
SecretKeyRingProtector subKeyProtector,
|
||||
SecretKeyRingProtector keyRingProtector)
|
||||
throws PGPException {
|
||||
|
||||
PGPPublicKey primaryKey = secretKeyRing.getSecretKey().getPublicKey();
|
||||
|
||||
PBESecretKeyDecryptor ringDecryptor = keyRingProtector.getDecryptor(primaryKey.getKeyID());
|
||||
PBESecretKeyEncryptor subKeyEncryptor = subKeyProtector.getEncryptor(secretSubKey.getKeyID());
|
||||
|
||||
PGPDigestCalculator digestCalculator = ImplementationFactory.getInstance().getV4FingerprintCalculator();
|
||||
PGPContentSignerBuilder contentSignerBuilder =
|
||||
SignatureUtils.getPgpContentSignerBuilderForKey(primaryKey);
|
||||
|
||||
PGPPrivateKey privateSubKey = UnlockSecretKey.unlockSecretKey(secretSubKey, subKeyProtector);
|
||||
PGPKeyPair subKeyPair = new PGPKeyPair(secretSubKey.getPublicKey(), privateSubKey);
|
||||
|
||||
PGPKeyRingGenerator keyRingGenerator = new PGPKeyRingGenerator(
|
||||
secretKeyRing, ringDecryptor, digestCalculator, contentSignerBuilder, subKeyEncryptor);
|
||||
|
||||
keyRingGenerator.addSubKey(subKeyPair, hashedSubpackets, unhashedSubpackets);
|
||||
secretKeyRing = keyRingGenerator.generateSecretKeyRing();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKeyRingEditorInterface addSubKey(PGPSecretKey subkey,
|
||||
public SecretKeyRingEditorInterface addSubKey(PGPKeyPair subkey,
|
||||
@Nullable SelfSignatureSubpackets.Callback bindingSignatureCallback,
|
||||
@Nullable SelfSignatureSubpackets.Callback backSignatureCallback,
|
||||
SecretKeyRingProtector subkeyProtector,
|
||||
SecretKeyRingProtector primaryKeyProtector,
|
||||
KeyFlag keyFlag,
|
||||
|
@ -193,36 +160,49 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
|||
SignatureSubpacketsUtil.assureKeyCanCarryFlags(subkeyAlgorithm);
|
||||
|
||||
PGPSecretKey primaryKey = secretKeyRing.getSecretKey();
|
||||
SubkeyBindingSignatureBuilder bindingSigBuilder =
|
||||
new SubkeyBindingSignatureBuilder(primaryKey, primaryKeyProtector);
|
||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeyRing);
|
||||
PublicKeyAlgorithm signingKeyAlgorithm = PublicKeyAlgorithm.fromId(primaryKey.getPublicKey().getAlgorithm());
|
||||
HashAlgorithm hashAlgorithm = HashAlgorithmNegotiator
|
||||
.negotiateSignatureHashAlgorithm(PGPainless.getPolicy())
|
||||
.negotiateHashAlgorithm(info.getPreferredHashAlgorithms());
|
||||
|
||||
bindingSigBuilder.applyCallback(bindingSignatureCallback);
|
||||
bindingSigBuilder.getHashedSubpackets().setKeyFlags(flags);
|
||||
// While we'd like to rely on our own BindingSignatureBuilder implementation,
|
||||
// unfortunately we have to use BCs PGPKeyRingGenerator class since there is no public constructor
|
||||
// for subkeys. See https://github.com/bcgit/bc-java/pull/1063
|
||||
PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
|
||||
secretKeyRing,
|
||||
primaryKeyProtector.getDecryptor(primaryKey.getKeyID()),
|
||||
ImplementationFactory.getInstance().getV4FingerprintCalculator(),
|
||||
ImplementationFactory.getInstance().getPGPContentSignerBuilder(
|
||||
signingKeyAlgorithm, hashAlgorithm),
|
||||
subkeyProtector.getEncryptor(subkey.getKeyID()));
|
||||
|
||||
SelfSignatureSubpackets hashedSubpackets = SignatureSubpackets.createHashedSubpackets(primaryKey.getPublicKey());
|
||||
SelfSignatureSubpackets unhashedSubpackets = SignatureSubpackets.createEmptySubpackets();
|
||||
hashedSubpackets.setKeyFlags(flags);
|
||||
|
||||
if (bindingSignatureCallback != null) {
|
||||
bindingSignatureCallback.modifyHashedSubpackets(hashedSubpackets);
|
||||
bindingSignatureCallback.modifyUnhashedSubpackets(unhashedSubpackets);
|
||||
}
|
||||
|
||||
boolean isSigningKey = CollectionUtils.contains(flags, KeyFlag.SIGN_DATA) ||
|
||||
CollectionUtils.contains(flags, KeyFlag.CERTIFY_OTHER);
|
||||
PGPContentSignerBuilder primaryKeyBindingSigner = null;
|
||||
if (isSigningKey) {
|
||||
// Add embedded back-signature made by subkey over primary key
|
||||
PrimaryKeyBindingSignatureBuilder backSigBuilder =
|
||||
new PrimaryKeyBindingSignatureBuilder(subkey, subkeyProtector);
|
||||
backSigBuilder.applyCallback(backSignatureCallback);
|
||||
PGPSignature backSig = backSigBuilder.build(primaryKey.getPublicKey());
|
||||
bindingSigBuilder.getHashedSubpackets().addEmbeddedSignature(backSig);
|
||||
primaryKeyBindingSigner = ImplementationFactory.getInstance().getPGPContentSignerBuilder(subkeyAlgorithm, hashAlgorithm);
|
||||
}
|
||||
|
||||
PGPSignature bindingSig = bindingSigBuilder.build(subkey.getPublicKey());
|
||||
subkey = KeyRingUtils.secretKeyPlusSignature(subkey, bindingSig);
|
||||
secretKeyRing = KeyRingUtils.secretKeysPlusSecretKey(secretKeyRing, subkey);
|
||||
ringGenerator.addSubKey(subkey,
|
||||
SignatureSubpacketsHelper.toVector((SignatureSubpackets) hashedSubpackets),
|
||||
SignatureSubpacketsHelper.toVector((SignatureSubpackets) unhashedSubpackets),
|
||||
primaryKeyBindingSigner);
|
||||
|
||||
secretKeyRing = ringGenerator.generateSecretKeyRing();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private PGPSecretKey generateSubKey(@Nonnull KeySpec keySpec,
|
||||
@Nonnull Passphrase subKeyPassphrase)
|
||||
throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
||||
return KeyRingBuilder.generatePGPSecretKey(keySpec, subKeyPassphrase, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKeyRingEditorInterface revoke(SecretKeyRingProtector secretKeyRingProtector,
|
||||
@Nullable RevocationAttributes revocationAttributes)
|
||||
|
@ -252,15 +232,13 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
|||
SecretKeyRingProtector secretKeyRingProtector,
|
||||
@Nullable RevocationSignatureSubpackets.Callback subpacketsCallback)
|
||||
throws PGPException {
|
||||
// retrieve subkey to be revoked
|
||||
PGPPublicKey revokeeSubKey = KeyRingUtils.requirePublicKeyFrom(secretKeyRing, keyID);
|
||||
// create revocation
|
||||
PGPSignature subKeyRevocation = generateRevocation(secretKeyRingProtector, revokeeSubKey,
|
||||
subpacketsCallback);
|
||||
revokeeSubKey = PGPPublicKey.addCertification(revokeeSubKey, subKeyRevocation);
|
||||
|
||||
// Inject revoked public key into key ring
|
||||
PGPPublicKeyRing publicKeyRing = KeyRingUtils.publicKeyRingFrom(secretKeyRing);
|
||||
publicKeyRing = PGPPublicKeyRing.insertPublicKey(publicKeyRing, revokeeSubKey);
|
||||
secretKeyRing = PGPSecretKeyRing.replacePublicKeys(secretKeyRing, publicKeyRing);
|
||||
// inject revocation sig into key ring
|
||||
secretKeyRing = KeyRingUtils.injectCertification(secretKeyRing, revokeeSubKey, subKeyRevocation);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -285,6 +263,16 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
|||
return generateRevocation(secretKeyRingProtector, revokeeSubkey, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PGPSignature createRevocationCertificate(
|
||||
long subkeyId,
|
||||
SecretKeyRingProtector secretKeyRingProtector,
|
||||
@Nullable RevocationSignatureSubpackets.Callback certificateSubpacketsCallback)
|
||||
throws PGPException {
|
||||
PGPPublicKey revokeeSubkey = KeyRingUtils.requirePublicKeyFrom(secretKeyRing, subkeyId);
|
||||
return generateRevocation(secretKeyRingProtector, revokeeSubkey, certificateSubpacketsCallback);
|
||||
}
|
||||
|
||||
private PGPSignature generateRevocation(SecretKeyRingProtector protector,
|
||||
PGPPublicKey revokeeSubKey,
|
||||
@Nullable RevocationSignatureSubpackets.Callback callback)
|
||||
|
@ -371,12 +359,7 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
|||
signatureBuilder.applyCallback(callback);
|
||||
|
||||
PGPSignature revocationSignature = signatureBuilder.build(userId);
|
||||
primaryPublicKey = PGPPublicKey.addCertification(primaryPublicKey, userId, revocationSignature);
|
||||
|
||||
PGPPublicKeyRing publicKeyRing = KeyRingUtils.publicKeyRingFrom(secretKeyRing);
|
||||
publicKeyRing = PGPPublicKeyRing.insertPublicKey(publicKeyRing, primaryPublicKey);
|
||||
secretKeyRing = PGPSecretKeyRing.replacePublicKeys(secretKeyRing, publicKeyRing);
|
||||
|
||||
secretKeyRing = KeyRingUtils.injectCertification(secretKeyRing, userId, revocationSignature);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,9 @@ import javax.annotation.Nonnull;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.PGPKeyPair;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||
import org.pgpainless.algorithm.KeyFlag;
|
||||
import org.pgpainless.key.OpenPgpFingerprint;
|
||||
import org.pgpainless.key.generation.KeySpec;
|
||||
|
@ -66,18 +65,10 @@ public interface SecretKeyRingEditorInterface {
|
|||
SecretKeyRingEditorInterface addSubKey(@Nonnull KeySpec keySpec,
|
||||
@Nullable Passphrase subKeyPassphrase,
|
||||
SecretKeyRingProtector secretKeyRingProtector)
|
||||
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException;
|
||||
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, IOException;
|
||||
|
||||
@Deprecated
|
||||
SecretKeyRingEditorInterface addSubKey(PGPSecretKey subKey,
|
||||
PGPSignatureSubpacketVector hashedSubpackets,
|
||||
PGPSignatureSubpacketVector unhashedSubpackets,
|
||||
SecretKeyRingProtector subKeyProtector, SecretKeyRingProtector keyRingProtector)
|
||||
throws PGPException;
|
||||
|
||||
SecretKeyRingEditorInterface addSubKey(PGPSecretKey subkey,
|
||||
SecretKeyRingEditorInterface addSubKey(PGPKeyPair subkey,
|
||||
@Nullable SelfSignatureSubpackets.Callback bindingSignatureCallback,
|
||||
@Nullable SelfSignatureSubpackets.Callback backSignatureCallback,
|
||||
SecretKeyRingProtector subkeyProtector,
|
||||
SecretKeyRingProtector primaryKeyProtector,
|
||||
KeyFlag keyFlag,
|
||||
|
@ -244,17 +235,22 @@ public interface SecretKeyRingEditorInterface {
|
|||
* @return revocation certificate
|
||||
*/
|
||||
PGPSignature createRevocationCertificate(SecretKeyRingProtector secretKeyRingProtector,
|
||||
RevocationAttributes revocationAttributes)
|
||||
@Nullable RevocationAttributes revocationAttributes)
|
||||
throws PGPException;
|
||||
|
||||
PGPSignature createRevocationCertificate(long subkeyId,
|
||||
SecretKeyRingProtector secretKeyRingProtector,
|
||||
RevocationAttributes revocationAttributes)
|
||||
@Nullable RevocationAttributes revocationAttributes)
|
||||
throws PGPException;
|
||||
|
||||
PGPSignature createRevocationCertificate(long subkeyId,
|
||||
SecretKeyRingProtector secretKeyRingProtector,
|
||||
@Nullable RevocationSignatureSubpackets.Callback certificateSubpacketsCallback)
|
||||
throws PGPException;
|
||||
|
||||
default PGPSignature createRevocationCertificate(OpenPgpFingerprint subkeyFingerprint,
|
||||
SecretKeyRingProtector secretKeyRingProtector,
|
||||
RevocationAttributes revocationAttributes)
|
||||
@Nullable RevocationAttributes revocationAttributes)
|
||||
throws PGPException {
|
||||
return createRevocationCertificate(subkeyFingerprint.getKeyId(), secretKeyRingProtector, revocationAttributes);
|
||||
}
|
||||
|
|
|
@ -22,9 +22,10 @@ import org.bouncycastle.openpgp.PGPSecretKey;
|
|||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||
import org.pgpainless.util.CollectionUtils;
|
||||
|
||||
public final class KeyRingUtils {
|
||||
|
||||
|
@ -203,22 +204,121 @@ public final class KeyRingUtils {
|
|||
return publicKeys;
|
||||
}
|
||||
|
||||
public static PGPSecretKeyRing secretKeysPlusPublicKey(PGPSecretKeyRing secretKeys, PGPPublicKey subkey) {
|
||||
PGPPublicKeyRing publicKeys = publicKeyRingFrom(secretKeys);
|
||||
PGPPublicKeyRing newPublicKeys = publicKeysPlusPublicKey(publicKeys, subkey);
|
||||
PGPSecretKeyRing newSecretKeys = PGPSecretKeyRing.replacePublicKeys(secretKeys, newPublicKeys);
|
||||
return newSecretKeys;
|
||||
public static <T extends PGPKeyRing> T injectCertification(T keyRing, PGPPublicKey certifiedKey, PGPSignature certification) {
|
||||
PGPSecretKeyRing secretKeys = null;
|
||||
PGPPublicKeyRing publicKeys;
|
||||
if (keyRing instanceof PGPSecretKeyRing) {
|
||||
secretKeys = (PGPSecretKeyRing) keyRing;
|
||||
publicKeys = PGPainless.extractCertificate(secretKeys);
|
||||
} else {
|
||||
publicKeys = (PGPPublicKeyRing) keyRing;
|
||||
}
|
||||
|
||||
certifiedKey = PGPPublicKey.addCertification(certifiedKey, certification);
|
||||
List<PGPPublicKey> publicKeyList = new ArrayList<>();
|
||||
Iterator<PGPPublicKey> publicKeyIterator = publicKeys.iterator();
|
||||
boolean added = false;
|
||||
while (publicKeyIterator.hasNext()) {
|
||||
PGPPublicKey key = publicKeyIterator.next();
|
||||
if (key.getKeyID() == certifiedKey.getKeyID()) {
|
||||
added = true;
|
||||
publicKeyList.add(certifiedKey);
|
||||
} else {
|
||||
publicKeyList.add(key);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
throw new NoSuchElementException("Cannot find public key with id " + Long.toHexString(certifiedKey.getKeyID()) + " in the provided key ring.");
|
||||
}
|
||||
|
||||
publicKeys = new PGPPublicKeyRing(publicKeyList);
|
||||
if (secretKeys == null) {
|
||||
return (T) publicKeys;
|
||||
} else {
|
||||
secretKeys = PGPSecretKeyRing.replacePublicKeys(secretKeys, publicKeys);
|
||||
return (T) secretKeys;
|
||||
}
|
||||
}
|
||||
|
||||
public static PGPPublicKeyRing publicKeysPlusPublicKey(PGPPublicKeyRing publicKeys, PGPPublicKey subkey) {
|
||||
List<PGPPublicKey> publicKeyList = CollectionUtils.iteratorToList(publicKeys.getPublicKeys());
|
||||
publicKeyList.add(subkey);
|
||||
PGPPublicKeyRing newPublicKeys = new PGPPublicKeyRing(publicKeyList);
|
||||
return newPublicKeys;
|
||||
public static <T extends PGPKeyRing> T injectCertification(T keyRing, String userId, PGPSignature certification) {
|
||||
PGPSecretKeyRing secretKeys = null;
|
||||
PGPPublicKeyRing publicKeys;
|
||||
if (keyRing instanceof PGPSecretKeyRing) {
|
||||
secretKeys = (PGPSecretKeyRing) keyRing;
|
||||
publicKeys = PGPainless.extractCertificate(secretKeys);
|
||||
} else {
|
||||
publicKeys = (PGPPublicKeyRing) keyRing;
|
||||
}
|
||||
|
||||
Iterator<PGPPublicKey> publicKeyIterator = publicKeys.iterator();
|
||||
PGPPublicKey primaryKey = publicKeyIterator.next();
|
||||
primaryKey = PGPPublicKey.addCertification(primaryKey, userId, certification);
|
||||
|
||||
List<PGPPublicKey> publicKeyList = new ArrayList<>();
|
||||
publicKeyList.add(primaryKey);
|
||||
while (publicKeyIterator.hasNext()) {
|
||||
publicKeyList.add(publicKeyIterator.next());
|
||||
}
|
||||
|
||||
publicKeys = new PGPPublicKeyRing(publicKeyList);
|
||||
if (secretKeys == null) {
|
||||
return (T) publicKeys;
|
||||
} else {
|
||||
secretKeys = PGPSecretKeyRing.replacePublicKeys(secretKeys, publicKeys);
|
||||
return (T) secretKeys;
|
||||
}
|
||||
}
|
||||
|
||||
public static PGPSecretKeyRing secretKeysPlusSecretKey(PGPSecretKeyRing secretKeys, PGPSecretKey subkey) {
|
||||
return PGPSecretKeyRing.insertSecretKey(secretKeys, subkey);
|
||||
public static <T extends PGPKeyRing> T injectCertification(T keyRing, PGPUserAttributeSubpacketVector userAttributes, PGPSignature certification) {
|
||||
PGPSecretKeyRing secretKeys = null;
|
||||
PGPPublicKeyRing publicKeys;
|
||||
if (keyRing instanceof PGPSecretKeyRing) {
|
||||
secretKeys = (PGPSecretKeyRing) keyRing;
|
||||
publicKeys = PGPainless.extractCertificate(secretKeys);
|
||||
} else {
|
||||
publicKeys = (PGPPublicKeyRing) keyRing;
|
||||
}
|
||||
|
||||
Iterator<PGPPublicKey> publicKeyIterator = publicKeys.iterator();
|
||||
PGPPublicKey primaryKey = publicKeyIterator.next();
|
||||
primaryKey = PGPPublicKey.addCertification(primaryKey, userAttributes, certification);
|
||||
|
||||
List<PGPPublicKey> publicKeyList = new ArrayList<>();
|
||||
publicKeyList.add(primaryKey);
|
||||
while (publicKeyIterator.hasNext()) {
|
||||
publicKeyList.add(publicKeyIterator.next());
|
||||
}
|
||||
|
||||
publicKeys = new PGPPublicKeyRing(publicKeyList);
|
||||
if (secretKeys == null) {
|
||||
return (T) publicKeys;
|
||||
} else {
|
||||
secretKeys = PGPSecretKeyRing.replacePublicKeys(secretKeys, publicKeys);
|
||||
return (T) secretKeys;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends PGPKeyRing> T keysPlusPublicKey(T keyRing, PGPPublicKey publicKey) {
|
||||
PGPSecretKeyRing secretKeys = null;
|
||||
PGPPublicKeyRing publicKeys;
|
||||
if (keyRing instanceof PGPSecretKeyRing) {
|
||||
secretKeys = (PGPSecretKeyRing) keyRing;
|
||||
publicKeys = PGPainless.extractCertificate(secretKeys);
|
||||
} else {
|
||||
publicKeys = (PGPPublicKeyRing) keyRing;
|
||||
}
|
||||
|
||||
publicKeys = PGPPublicKeyRing.insertPublicKey(publicKeys, publicKey);
|
||||
if (secretKeys == null) {
|
||||
return (T) publicKeys;
|
||||
} else {
|
||||
secretKeys = PGPSecretKeyRing.replacePublicKeys(secretKeys, publicKeys);
|
||||
return (T) secretKeys;
|
||||
}
|
||||
}
|
||||
|
||||
public static PGPSecretKeyRing keysPlusSecretKey(PGPSecretKeyRing secretKeys, PGPSecretKey secretKey) {
|
||||
return PGPSecretKeyRing.insertSecretKey(secretKeys, secretKey);
|
||||
}
|
||||
|
||||
public static PGPSecretKey secretKeyPlusSignature(PGPSecretKey secretKey, PGPSignature signature) {
|
||||
|
@ -227,4 +327,5 @@ public final class KeyRingUtils {
|
|||
PGPSecretKey newSecretKey = PGPSecretKey.replacePublicKey(secretKey, publicKey);
|
||||
return newSecretKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,18 +4,14 @@
|
|||
|
||||
package org.pgpainless.signature.builder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.pgpainless.algorithm.KeyFlag;
|
||||
import org.pgpainless.algorithm.SignatureType;
|
||||
import org.pgpainless.exception.WrongPassphraseException;
|
||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||
import org.pgpainless.signature.subpackets.BaseSignatureSubpackets;
|
||||
import org.pgpainless.signature.subpackets.CertificationSubpackets;
|
||||
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
||||
|
||||
public final class SignatureFactory {
|
||||
|
@ -24,66 +20,14 @@ public final class SignatureFactory {
|
|||
|
||||
}
|
||||
|
||||
public static SubkeyBindingSignatureBuilder bindNonSigningSubkey(
|
||||
public static SelfSignatureBuilder selfCertifyUserId(
|
||||
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.\n" +
|
||||
"Please use the method bindSigningSubkey() instead.");
|
||||
}
|
||||
|
||||
return bindSubkey(primaryKey, primaryKeyProtector, subkeyBindingSubpacketsCallback, flags);
|
||||
}
|
||||
|
||||
public static SubkeyBindingSignatureBuilder bindSigningSubkey(
|
||||
PGPSecretKey primaryKey,
|
||||
SecretKeyRingProtector primaryKeyProtector,
|
||||
PGPSecretKey subkey,
|
||||
SecretKeyRingProtector subkeyProtector,
|
||||
@Nullable SelfSignatureSubpackets.Callback subkeyBindingSubpacketsCallback,
|
||||
@Nullable SelfSignatureSubpackets.Callback primaryKeyBindingSubpacketsCallback,
|
||||
KeyFlag... flags)
|
||||
throws PGPException, IOException {
|
||||
|
||||
SubkeyBindingSignatureBuilder subkeyBinder = bindSubkey(primaryKey, primaryKeyProtector, subkeyBindingSubpacketsCallback, flags);
|
||||
|
||||
if (hasSignDataFlag(flags)) {
|
||||
PGPSignature backsig = bindPrimaryKey(
|
||||
subkey, subkeyProtector, primaryKeyBindingSubpacketsCallback)
|
||||
.build(primaryKey.getPublicKey());
|
||||
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();
|
||||
hashedSubpackets.setKeyFlags(flags);
|
||||
|
||||
subkeyBinder.applyCallback(subkeyBindingSubpacketsCallback);
|
||||
|
||||
return subkeyBinder;
|
||||
}
|
||||
|
||||
public static PrimaryKeyBindingSignatureBuilder bindPrimaryKey(
|
||||
PGPSecretKey subkey,
|
||||
SecretKeyRingProtector subkeyProtector,
|
||||
@Nullable SelfSignatureSubpackets.Callback primaryKeyBindingSubpacketsCallback) throws WrongPassphraseException {
|
||||
PrimaryKeyBindingSignatureBuilder primaryKeyBinder = new PrimaryKeyBindingSignatureBuilder(subkey, subkeyProtector);
|
||||
|
||||
primaryKeyBinder.applyCallback(primaryKeyBindingSubpacketsCallback);
|
||||
|
||||
return primaryKeyBinder;
|
||||
@Nullable SelfSignatureSubpackets.Callback selfSignatureCallback,
|
||||
List<KeyFlag> keyFlags)
|
||||
throws WrongPassphraseException {
|
||||
KeyFlag[] keyFlagArray = keyFlags.toArray(new KeyFlag[0]);
|
||||
return selfCertifyUserId(primaryKey, primaryKeyProtector, selfSignatureCallback, keyFlagArray);
|
||||
}
|
||||
|
||||
public static SelfSignatureBuilder selfCertifyUserId(
|
||||
|
@ -100,55 +44,4 @@ public final class SignatureFactory {
|
|||
return certifier;
|
||||
}
|
||||
|
||||
public static SelfSignatureBuilder renewSelfCertification(
|
||||
PGPSecretKey primaryKey,
|
||||
SecretKeyRingProtector primaryKeyProtector,
|
||||
@Nullable SelfSignatureSubpackets.Callback selfSignatureCallback,
|
||||
PGPSignature oldCertification) throws WrongPassphraseException {
|
||||
SelfSignatureBuilder certifier = new SelfSignatureBuilder(
|
||||
primaryKey, primaryKeyProtector, oldCertification);
|
||||
|
||||
certifier.applyCallback(selfSignatureCallback);
|
||||
|
||||
return certifier;
|
||||
}
|
||||
|
||||
public static CertificationSignatureBuilder certifyUserId(
|
||||
PGPSecretKey signingKey,
|
||||
SecretKeyRingProtector signingKeyProtector,
|
||||
@Nullable CertificationSubpackets.Callback subpacketsCallback)
|
||||
throws WrongPassphraseException {
|
||||
CertificationSignatureBuilder certifier = new CertificationSignatureBuilder(signingKey, signingKeyProtector);
|
||||
|
||||
certifier.applyCallback(subpacketsCallback);
|
||||
|
||||
return certifier;
|
||||
}
|
||||
|
||||
public static UniversalSignatureBuilder universalSignature(
|
||||
SignatureType signatureType,
|
||||
PGPSecretKey signingKey,
|
||||
SecretKeyRingProtector signingKeyProtector,
|
||||
@Nullable BaseSignatureSubpackets.Callback callback)
|
||||
throws WrongPassphraseException {
|
||||
UniversalSignatureBuilder builder =
|
||||
new UniversalSignatureBuilder(signatureType, signingKey, signingKeyProtector);
|
||||
|
||||
builder.applyCallback(callback);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static boolean hasSignDataFlag(KeyFlag... flags) {
|
||||
if (flags == null) {
|
||||
return false;
|
||||
}
|
||||
for (KeyFlag flag : flags) {
|
||||
if (flag == KeyFlag.SIGN_DATA) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ public class ModifyKeys {
|
|||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
@Test
|
||||
public void addSubkey() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
||||
public void addSubkey() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
|
||||
// Protector for unlocking the existing secret key
|
||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAllKeysWith(Passphrase.fromPassword(originalPassphrase), secretKey);
|
||||
Passphrase subkeyPassphrase = Passphrase.fromPassword("subk3yP4ssphr4s3");
|
||||
|
|
|
@ -16,28 +16,28 @@ import java.util.List;
|
|||
|
||||
import org.bouncycastle.bcpg.sig.NotationData;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPKeyPair;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.junit.JUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.algorithm.EncryptionPurpose;
|
||||
import org.pgpainless.algorithm.KeyFlag;
|
||||
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
||||
import org.pgpainless.key.generation.KeyRingBuilder;
|
||||
import org.pgpainless.key.generation.KeySpec;
|
||||
import org.pgpainless.key.generation.type.KeyType;
|
||||
import org.pgpainless.key.generation.type.xdh.XDHSpec;
|
||||
import org.pgpainless.key.generation.type.eddsa.EdDSACurve;
|
||||
import org.pgpainless.key.info.KeyRingInfo;
|
||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||
import org.pgpainless.util.Passphrase;
|
||||
|
||||
public class AddSubkeyWithModifiedBindingSignatureSubpackets {
|
||||
|
||||
public static long MILLIS_IN_SEC = 1000;
|
||||
|
||||
@Test
|
||||
public void bindEncryptionSubkeyAndModifyBindingSignatureHashedSubpackets() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
|
||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||
|
@ -45,29 +45,30 @@ public class AddSubkeyWithModifiedBindingSignatureSubpackets {
|
|||
.modernKeyRing("Alice <alice@pgpainless.org>", null);
|
||||
KeyRingInfo before = PGPainless.inspectKeyRing(secretKeys);
|
||||
|
||||
PGPSecretKey secretSubkey = KeyRingBuilder.generatePGPSecretKey(
|
||||
KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_COMMS).build(),
|
||||
Passphrase.emptyPassphrase(), false);
|
||||
PGPKeyPair secretSubkey = KeyRingBuilder.generateKeyPair(
|
||||
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.SIGN_DATA).build());
|
||||
|
||||
long secondsUntilExpiration = 1000;
|
||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
||||
.addSubKey(secretSubkey, new SelfSignatureSubpackets.Callback() {
|
||||
@Override
|
||||
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
||||
hashedSubpackets.setKeyExpirationTime(true, 1000);
|
||||
hashedSubpackets.addNotationData(false, "test@test.test", "test");
|
||||
}
|
||||
}, null, SecretKeyRingProtector.unprotectedKeys(), protector, KeyFlag.ENCRYPT_COMMS)
|
||||
@Override
|
||||
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
||||
hashedSubpackets.setKeyExpirationTime(true, secondsUntilExpiration);
|
||||
hashedSubpackets.addNotationData(false, "test@test.test", "test");
|
||||
}
|
||||
}, SecretKeyRingProtector.unprotectedKeys(), protector, KeyFlag.SIGN_DATA)
|
||||
.done();
|
||||
|
||||
KeyRingInfo after = PGPainless.inspectKeyRing(secretKeys);
|
||||
List<PGPPublicKey> signingKeys = after.getSigningSubkeys();
|
||||
signingKeys.removeAll(before.getSigningSubkeys());
|
||||
assertFalse(signingKeys.isEmpty());
|
||||
|
||||
List<PGPPublicKey> encryptionKeys = after.getEncryptionSubkeys(EncryptionPurpose.COMMUNICATIONS);
|
||||
encryptionKeys.removeAll(before.getEncryptionSubkeys(EncryptionPurpose.COMMUNICATIONS));
|
||||
assertFalse(encryptionKeys.isEmpty());
|
||||
assertEquals(1, encryptionKeys.size());
|
||||
|
||||
PGPPublicKey newKey = encryptionKeys.get(0);
|
||||
JUtils.assertEquals(new Date().getTime() + 1000 * 1000, after.getSubkeyExpirationDate(new OpenPgpV4Fingerprint(newKey)).getTime(), 2000);
|
||||
PGPPublicKey newKey = signingKeys.get(0);
|
||||
Date now = new Date();
|
||||
JUtils.assertEquals(
|
||||
now.getTime() + MILLIS_IN_SEC * secondsUntilExpiration,
|
||||
after.getSubkeyExpirationDate(new OpenPgpV4Fingerprint(newKey)).getTime(), 2 * MILLIS_IN_SEC);
|
||||
assertTrue(newKey.getSignatures().hasNext());
|
||||
PGPSignature binding = newKey.getSignatures().next();
|
||||
List<NotationData> notations = SignatureSubpacketsUtil.getHashedNotationData(binding);
|
||||
|
|
|
@ -39,7 +39,6 @@ import org.pgpainless.key.util.RevocationAttributes;
|
|||
import org.pgpainless.signature.SignatureUtils;
|
||||
import org.pgpainless.signature.subpackets.RevocationSignatureSubpackets;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||
import org.pgpainless.util.ArmorUtils;
|
||||
import org.pgpainless.util.Passphrase;
|
||||
|
||||
public class RevokeSubKeyTest {
|
||||
|
@ -82,11 +81,6 @@ public class RevokeSubKeyTest {
|
|||
.withReason(RevocationAttributes.Reason.KEY_RETIRED)
|
||||
.withDescription("Key no longer used."));
|
||||
|
||||
// CHECKSTYLE:OFF
|
||||
System.out.println("Revocation Certificate:");
|
||||
System.out.println(ArmorUtils.toAsciiArmoredString(revocationCertificate.getEncoded()));
|
||||
// CHECKSTYLE:ON
|
||||
|
||||
PGPPublicKey publicKey = secretKeys.getPublicKey();
|
||||
assertFalse(publicKey.hasRevocation());
|
||||
|
||||
|
@ -107,8 +101,8 @@ public class RevokeSubKeyTest {
|
|||
.forKey(secretKeys, Passphrase.fromPassword("password123"));
|
||||
|
||||
SecretKeyRingEditorInterface editor = PGPainless.modifyKeyRing(secretKeys);
|
||||
PGPSignature keyRevocation = editor.createRevocationCertificate(primaryKey.getKeyID(), protector, null);
|
||||
PGPSignature subkeyRevocation = editor.createRevocationCertificate(subKey.getKeyID(), protector, null);
|
||||
PGPSignature keyRevocation = editor.createRevocationCertificate(primaryKey.getKeyID(), protector, (RevocationAttributes) null);
|
||||
PGPSignature subkeyRevocation = editor.createRevocationCertificate(subKey.getKeyID(), protector, (RevocationAttributes) null);
|
||||
|
||||
assertEquals(SignatureType.KEY_REVOCATION.getCode(), keyRevocation.getSignatureType());
|
||||
assertEquals(SignatureType.SUBKEY_REVOCATION.getCode(), subkeyRevocation.getSignatureType());
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.signature.builder;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.bouncycastle.bcpg.sig.NotationData;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.algorithm.EncryptionPurpose;
|
||||
import org.pgpainless.algorithm.KeyFlag;
|
||||
import org.pgpainless.key.info.KeyRingInfo;
|
||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||
import org.pgpainless.util.Passphrase;
|
||||
|
||||
public class SubkeyBindingSignatureBuilderTest {
|
||||
|
||||
@Test
|
||||
public void testBindSubkeyWithCustomNotation() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
|
||||
PGPSecretKeyRing secretKey = PGPainless.generateKeyRing()
|
||||
.modernKeyRing("Alice <alice@pgpainless.org>", "passphrase");
|
||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKey);
|
||||
List<PGPPublicKey> previousSubkeys = info.getEncryptionSubkeys(EncryptionPurpose.ANY);
|
||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAllKeysWith(Passphrase.fromPassword("passphrase"), secretKey);
|
||||
|
||||
PGPSecretKeyRing tempSubkeyRing = PGPainless.generateKeyRing()
|
||||
.modernKeyRing("Subkeys", null);
|
||||
PGPPublicKey subkeyPub = PGPainless.inspectKeyRing(tempSubkeyRing)
|
||||
.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0);
|
||||
PGPSecretKey subkeySec = tempSubkeyRing.getSecretKey(subkeyPub.getKeyID());
|
||||
|
||||
PGPSignature binding = SignatureFactory.bindNonSigningSubkey(
|
||||
secretKey.getSecretKey(), protector,
|
||||
new SelfSignatureSubpackets.Callback() {
|
||||
@Override
|
||||
public void modifyHashedSubpackets(SelfSignatureSubpackets subpackets) {
|
||||
subpackets.addNotationData(false, "testnotation@pgpainless.org", "hello-world");
|
||||
}
|
||||
}, 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);
|
||||
List<PGPPublicKey> nextSubkeys = info.getEncryptionSubkeys(EncryptionPurpose.ANY);
|
||||
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