mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-23 11:27:57 +01:00
Fix errors
This commit is contained in:
parent
c31fda95f9
commit
04ada88188
12 changed files with 232 additions and 43 deletions
|
@ -109,4 +109,13 @@ public enum KeyFlag {
|
||||||
public static boolean hasKeyFlag(int mask, KeyFlag flag) {
|
public static boolean hasKeyFlag(int mask, KeyFlag flag) {
|
||||||
return (mask & flag.getFlag()) == flag.getFlag();
|
return (mask & flag.getFlag()) == flag.getFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean containsAny(int mask, KeyFlag... flags) {
|
||||||
|
for (KeyFlag flag : flags) {
|
||||||
|
if (hasKeyFlag(mask, flag)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.pgpainless.key.generation.type.KeyType;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
import org.pgpainless.provider.ProviderFactory;
|
import org.pgpainless.provider.ProviderFactory;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorUtil;
|
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorUtil;
|
||||||
|
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorWrapper;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
|
||||||
public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
||||||
|
@ -110,7 +111,9 @@ public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasCertifyOthersFlag(KeySpec keySpec) {
|
private boolean hasCertifyOthersFlag(KeySpec keySpec) {
|
||||||
return SignatureSubpacketGeneratorUtil.hasKeyFlag(KeyFlag.CERTIFY_OTHER, keySpec.getSubpacketGenerator());
|
return SignatureSubpacketGeneratorUtil.hasKeyFlag(KeyFlag.CERTIFY_OTHER,
|
||||||
|
keySpec.getSubpacketGenerator() == null ? null :
|
||||||
|
keySpec.getSubpacketGenerator().getGenerator());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean keyIsCertificationCapable(KeySpec keySpec) {
|
private boolean keyIsCertificationCapable(KeySpec keySpec) {
|
||||||
|
@ -135,13 +138,12 @@ public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
||||||
PGPKeyPair certKey = generateKeyPair(primaryKeySpec);
|
PGPKeyPair certKey = generateKeyPair(primaryKeySpec);
|
||||||
PGPContentSignerBuilder signer = buildContentSigner(certKey);
|
PGPContentSignerBuilder signer = buildContentSigner(certKey);
|
||||||
signatureGenerator = new PGPSignatureGenerator(signer);
|
signatureGenerator = new PGPSignatureGenerator(signer);
|
||||||
PGPSignatureSubpacketGenerator hashedSubPacketGenerator = primaryKeySpec.getSubpacketGenerator();
|
SignatureSubpacketGeneratorWrapper hashedSubPacketGenerator = primaryKeySpec.getSubpacketGenerator();
|
||||||
hashedSubPacketGenerator.setPrimaryUserID(false, true);
|
hashedSubPacketGenerator.setPrimaryUserId();
|
||||||
if (expirationDate != null) {
|
if (expirationDate != null) {
|
||||||
SignatureSubpacketGeneratorUtil.setKeyExpirationDateInSubpacketGenerator(
|
hashedSubPacketGenerator.setKeyExpirationTime(certKey.getPublicKey(), expirationDate);
|
||||||
expirationDate, new Date(), hashedSubPacketGenerator);
|
|
||||||
}
|
}
|
||||||
PGPSignatureSubpacketVector hashedSubPackets = hashedSubPacketGenerator.generate();
|
PGPSignatureSubpacketVector hashedSubPackets = hashedSubPacketGenerator.getGenerator().generate();
|
||||||
|
|
||||||
// Generator which the user can get the key pair from
|
// Generator which the user can get the key pair from
|
||||||
PGPKeyRingGenerator ringGenerator = buildRingGenerator(certKey, signer, hashedSubPackets);
|
PGPKeyRingGenerator ringGenerator = buildRingGenerator(certKey, signer, hashedSubPackets);
|
||||||
|
|
|
@ -5,21 +5,30 @@
|
||||||
package org.pgpainless.key.generation;
|
package org.pgpainless.key.generation;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
import org.pgpainless.algorithm.KeyFlag;
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
import org.pgpainless.key.generation.type.KeyType;
|
import org.pgpainless.key.generation.type.KeyType;
|
||||||
|
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorWrapper;
|
||||||
|
|
||||||
public class KeySpec {
|
public class KeySpec {
|
||||||
|
|
||||||
private final KeyType keyType;
|
private final KeyType keyType;
|
||||||
private final PGPSignatureSubpacketGenerator subpacketGenerator;
|
private final SignatureSubpacketGeneratorWrapper subpacketGenerator;
|
||||||
private final boolean inheritedSubPackets;
|
private final boolean inheritedSubPackets;
|
||||||
|
|
||||||
KeySpec(@Nonnull KeyType type,
|
KeySpec(@Nonnull KeyType type,
|
||||||
@Nullable PGPSignatureSubpacketGenerator subpacketGenerator,
|
@Nonnull PGPSignatureSubpacketGenerator subpacketGenerator,
|
||||||
|
boolean inheritedSubPackets) {
|
||||||
|
this(
|
||||||
|
type,
|
||||||
|
SignatureSubpacketGeneratorWrapper.createSubpacketsFrom(subpacketGenerator.generate()),
|
||||||
|
inheritedSubPackets);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeySpec(@Nonnull KeyType type,
|
||||||
|
@Nonnull SignatureSubpacketGeneratorWrapper subpacketGenerator,
|
||||||
boolean inheritedSubPackets) {
|
boolean inheritedSubPackets) {
|
||||||
this.keyType = type;
|
this.keyType = type;
|
||||||
this.subpacketGenerator = subpacketGenerator;
|
this.subpacketGenerator = subpacketGenerator;
|
||||||
|
@ -31,12 +40,13 @@ public class KeySpec {
|
||||||
return keyType;
|
return keyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nonnull
|
||||||
public PGPSignatureSubpacketVector getSubpackets() {
|
public PGPSignatureSubpacketVector getSubpackets() {
|
||||||
return subpacketGenerator != null ? subpacketGenerator.generate() : null;
|
return subpacketGenerator.getGenerator().generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPSignatureSubpacketGenerator getSubpacketGenerator() {
|
@Nonnull
|
||||||
|
SignatureSubpacketGeneratorWrapper getSubpacketGenerator() {
|
||||||
return subpacketGenerator;
|
return subpacketGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.pgpainless.algorithm.HashAlgorithm;
|
||||||
import org.pgpainless.algorithm.KeyFlag;
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import org.pgpainless.key.generation.type.KeyType;
|
import org.pgpainless.key.generation.type.KeyType;
|
||||||
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||||
import org.pgpainless.util.CollectionUtils;
|
import org.pgpainless.util.CollectionUtils;
|
||||||
|
|
||||||
public class KeySpecBuilder implements KeySpecBuilderInterface {
|
public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
|
@ -39,7 +40,7 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
throw new IllegalArgumentException("List of additional flags MUST NOT be null.");
|
throw new IllegalArgumentException("List of additional flags MUST NOT be null.");
|
||||||
}
|
}
|
||||||
flags = CollectionUtils.concat(flag, flags);
|
flags = CollectionUtils.concat(flag, flags);
|
||||||
assureKeyCanCarryFlags(type, flags);
|
SignatureSubpacketsUtil.assureKeyCanCarryFlags(type, flags);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.keyFlags = flags;
|
this.keyFlags = flags;
|
||||||
}
|
}
|
||||||
|
@ -100,28 +101,4 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
}
|
}
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assureKeyCanCarryFlags(KeyType type, KeyFlag... flags) {
|
|
||||||
final int mask = KeyFlag.toBitmask(flags);
|
|
||||||
|
|
||||||
if (!type.canCertify() && KeyFlag.hasKeyFlag(mask, KeyFlag.CERTIFY_OTHER)) {
|
|
||||||
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag CERTIFY_OTHER.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!type.canSign() && KeyFlag.hasKeyFlag(mask, KeyFlag.SIGN_DATA)) {
|
|
||||||
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag SIGN_DATA.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!type.canEncryptCommunication() && KeyFlag.hasKeyFlag(mask, KeyFlag.ENCRYPT_COMMS)) {
|
|
||||||
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag ENCRYPT_COMMS.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!type.canEncryptStorage() && KeyFlag.hasKeyFlag(mask, KeyFlag.ENCRYPT_STORAGE)) {
|
|
||||||
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag ENCRYPT_STORAGE.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!type.canAuthenticate() && KeyFlag.hasKeyFlag(mask, KeyFlag.AUTHENTICATION)) {
|
|
||||||
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag AUTHENTIACTION.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
package org.pgpainless.key.modification.secretkeyring;
|
package org.pgpainless.key.modification.secretkeyring;
|
||||||
|
|
||||||
|
import static org.pgpainless.util.CollectionUtils.concat;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -35,6 +38,8 @@ import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
|
||||||
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder;
|
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder;
|
||||||
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
|
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
|
||||||
import org.pgpainless.algorithm.HashAlgorithm;
|
import org.pgpainless.algorithm.HashAlgorithm;
|
||||||
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
|
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||||
import org.pgpainless.algorithm.SignatureType;
|
import org.pgpainless.algorithm.SignatureType;
|
||||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import org.pgpainless.implementation.ImplementationFactory;
|
import org.pgpainless.implementation.ImplementationFactory;
|
||||||
|
@ -52,9 +57,13 @@ import org.pgpainless.key.protection.passphrase_provider.SolitaryPassphraseProvi
|
||||||
import org.pgpainless.key.util.KeyRingUtils;
|
import org.pgpainless.key.util.KeyRingUtils;
|
||||||
import org.pgpainless.key.util.RevocationAttributes;
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.signature.SignatureUtils;
|
import org.pgpainless.signature.SignatureUtils;
|
||||||
|
import org.pgpainless.signature.builder.PrimaryKeyBindingSignatureBuilder;
|
||||||
import org.pgpainless.signature.builder.SelfSignatureBuilder;
|
import org.pgpainless.signature.builder.SelfSignatureBuilder;
|
||||||
|
import org.pgpainless.signature.builder.SubkeyBindingSignatureBuilder;
|
||||||
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorUtil;
|
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorUtil;
|
||||||
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||||
|
import org.pgpainless.util.CollectionUtils;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
|
||||||
public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
|
@ -134,6 +143,7 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public SecretKeyRingEditorInterface addSubKey(PGPSecretKey secretSubKey,
|
public SecretKeyRingEditorInterface addSubKey(PGPSecretKey secretSubKey,
|
||||||
PGPSignatureSubpacketVector hashedSubpackets,
|
PGPSignatureSubpacketVector hashedSubpackets,
|
||||||
PGPSignatureSubpacketVector unhashedSubpackets,
|
PGPSignatureSubpacketVector unhashedSubpackets,
|
||||||
|
@ -163,6 +173,79 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SecretKeyRingEditorInterface addSubKey(PGPSecretKey subkey,
|
||||||
|
@Nullable SelfSignatureSubpackets.Callback bindingSignatureCallback,
|
||||||
|
@Nullable SelfSignatureSubpackets.Callback backSignatureCallback,
|
||||||
|
SecretKeyRingProtector subkeyProtector,
|
||||||
|
SecretKeyRingProtector primaryKeyProtector,
|
||||||
|
KeyFlag keyFlag,
|
||||||
|
KeyFlag... additionalKeyFlags) throws PGPException, IOException {
|
||||||
|
KeyFlag[] flags = concat(keyFlag, additionalKeyFlags);
|
||||||
|
SignatureSubpacketsUtil.assureKeyCanCarryFlags(PublicKeyAlgorithm.fromId(subkey.getPublicKey().getAlgorithm()));
|
||||||
|
|
||||||
|
boolean isSigningKey = CollectionUtils.contains(flags, KeyFlag.SIGN_DATA) ||
|
||||||
|
CollectionUtils.contains(flags, KeyFlag.CERTIFY_OTHER);
|
||||||
|
if (!isSigningKey) {
|
||||||
|
return addSubKey(subkey.getPublicKey(),
|
||||||
|
bindingSignatureCallback,
|
||||||
|
primaryKeyProtector,
|
||||||
|
keyFlag,
|
||||||
|
additionalKeyFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
PGPSecretKey primaryKey = secretKeyRing.getSecretKey();
|
||||||
|
SubkeyBindingSignatureBuilder bindingSigBuilder = new SubkeyBindingSignatureBuilder(primaryKey, primaryKeyProtector);
|
||||||
|
bindingSigBuilder.applyCallback(bindingSignatureCallback);
|
||||||
|
bindingSigBuilder.getHashedSubpackets().setKeyFlags(flags);
|
||||||
|
|
||||||
|
PrimaryKeyBindingSignatureBuilder backSigBuilder = new PrimaryKeyBindingSignatureBuilder(subkey, subkeyProtector);
|
||||||
|
backSigBuilder.applyCallback(backSignatureCallback);
|
||||||
|
PGPSignature backSig = backSigBuilder.build(primaryKey.getPublicKey());
|
||||||
|
|
||||||
|
bindingSigBuilder.getHashedSubpackets().addEmbeddedSignature(backSig);
|
||||||
|
PGPSignature bindingSig = bindingSigBuilder.build(subkey.getPublicKey());
|
||||||
|
subkey = KeyRingUtils.secretKeyPlusSignature(subkey, bindingSig);
|
||||||
|
secretKeyRing = KeyRingUtils.secretKeysPlusSecretKey(secretKeyRing, subkey);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SecretKeyRingEditorInterface addSubKey(PGPPublicKey subkey,
|
||||||
|
SelfSignatureSubpackets.Callback bindingSignatureCallback,
|
||||||
|
SecretKeyRingProtector primaryKeyProtector,
|
||||||
|
KeyFlag keyFlag,
|
||||||
|
KeyFlag... additionalKeyFlags) throws PGPException {
|
||||||
|
KeyFlag[] flags = concat(keyFlag, additionalKeyFlags);
|
||||||
|
boolean isSigningKey = CollectionUtils.contains(flags, KeyFlag.SIGN_DATA) ||
|
||||||
|
CollectionUtils.contains(flags, KeyFlag.CERTIFY_OTHER);
|
||||||
|
if (isSigningKey) {
|
||||||
|
throw new IllegalArgumentException("Cannot bind a signing capable subkey without access to the secret subkey.\n" +
|
||||||
|
"Please use addSubKey(PGPSecretKey secretSubKey, [...]) instead.");
|
||||||
|
}
|
||||||
|
|
||||||
|
PGPSignature bindingSignature = createSubkeyBindingSignature(subkey, bindingSignatureCallback, primaryKeyProtector, flags);
|
||||||
|
subkey = PGPPublicKey.addCertification(subkey, bindingSignature);
|
||||||
|
|
||||||
|
secretKeyRing = KeyRingUtils.secretKeysPlusPublicKey(secretKeyRing, subkey);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PGPSignature createSubkeyBindingSignature(PGPPublicKey subkey,
|
||||||
|
SelfSignatureSubpackets.Callback bindingSignatureCallback,
|
||||||
|
SecretKeyRingProtector primaryKeyProtector,
|
||||||
|
KeyFlag... keyFlags) throws PGPException {
|
||||||
|
PGPSecretKey primaryKey = secretKeyRing.getSecretKey();
|
||||||
|
SubkeyBindingSignatureBuilder builder = new SubkeyBindingSignatureBuilder(primaryKey, primaryKeyProtector);
|
||||||
|
builder.applyCallback(bindingSignatureCallback);
|
||||||
|
builder.getHashedSubpackets().setKeyFlags(keyFlags);
|
||||||
|
|
||||||
|
PGPSignature signature = builder.build(subkey);
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
private PGPSecretKey generateSubKey(@Nonnull KeySpec keySpec,
|
private PGPSecretKey generateSubKey(@Nonnull KeySpec keySpec,
|
||||||
@Nonnull Passphrase subKeyPassphrase)
|
@Nonnull Passphrase subKeyPassphrase)
|
||||||
throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
package org.pgpainless.key.modification.secretkeyring;
|
package org.pgpainless.key.modification.secretkeyring;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -11,16 +12,19 @@ import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
import org.pgpainless.key.OpenPgpFingerprint;
|
import org.pgpainless.key.OpenPgpFingerprint;
|
||||||
import org.pgpainless.key.generation.KeySpec;
|
import org.pgpainless.key.generation.KeySpec;
|
||||||
import org.pgpainless.key.protection.KeyRingProtectionSettings;
|
import org.pgpainless.key.protection.KeyRingProtectionSettings;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.util.RevocationAttributes;
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.key.util.UserId;
|
import org.pgpainless.key.util.UserId;
|
||||||
|
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
|
||||||
public interface SecretKeyRingEditorInterface {
|
public interface SecretKeyRingEditorInterface {
|
||||||
|
@ -59,11 +63,27 @@ public interface SecretKeyRingEditorInterface {
|
||||||
SecretKeyRingProtector secretKeyRingProtector)
|
SecretKeyRingProtector secretKeyRingProtector)
|
||||||
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException;
|
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
SecretKeyRingEditorInterface addSubKey(PGPSecretKey subKey,
|
SecretKeyRingEditorInterface addSubKey(PGPSecretKey subKey,
|
||||||
PGPSignatureSubpacketVector hashedSubpackets,
|
PGPSignatureSubpacketVector hashedSubpackets,
|
||||||
PGPSignatureSubpacketVector unhashedSubpackets,
|
PGPSignatureSubpacketVector unhashedSubpackets,
|
||||||
SecretKeyRingProtector subKeyProtector, SecretKeyRingProtector keyRingProtector)
|
SecretKeyRingProtector subKeyProtector, SecretKeyRingProtector keyRingProtector)
|
||||||
throws PGPException;
|
throws PGPException;
|
||||||
|
|
||||||
|
SecretKeyRingEditorInterface addSubKey(PGPSecretKey subkey,
|
||||||
|
@Nullable SelfSignatureSubpackets.Callback bindingSignatureCallback,
|
||||||
|
@Nullable SelfSignatureSubpackets.Callback backSignatureCallback,
|
||||||
|
SecretKeyRingProtector subkeyProtector,
|
||||||
|
SecretKeyRingProtector primaryKeyProtector,
|
||||||
|
KeyFlag keyFlag,
|
||||||
|
KeyFlag... additionalKeyFlags) throws PGPException, IOException;
|
||||||
|
|
||||||
|
SecretKeyRingEditorInterface addSubKey(PGPPublicKey subkey,
|
||||||
|
SelfSignatureSubpackets.Callback bindingSignatureCallback,
|
||||||
|
SecretKeyRingProtector primaryKeyProtector,
|
||||||
|
KeyFlag keyFlag,
|
||||||
|
KeyFlag... additionalKeyFlags) throws PGPException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revoke the key ring.
|
* Revoke the key ring.
|
||||||
* The revocation will be a hard revocation, rendering the whole key invalid for any past or future signatures.
|
* The revocation will be a hard revocation, rendering the whole key invalid for any past or future signatures.
|
||||||
|
|
|
@ -21,8 +21,10 @@ import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
|
import org.pgpainless.util.CollectionUtils;
|
||||||
|
|
||||||
public final class KeyRingUtils {
|
public final class KeyRingUtils {
|
||||||
|
|
||||||
|
@ -200,4 +202,29 @@ public final class KeyRingUtils {
|
||||||
publicKeys = PGPPublicKeyRing.insertPublicKey(publicKeys, publicKey);
|
publicKeys = PGPPublicKeyRing.insertPublicKey(publicKeys, publicKey);
|
||||||
return publicKeys;
|
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 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 PGPSecretKeyRing secretKeysPlusSecretKey(PGPSecretKeyRing secretKeys, PGPSecretKey subkey) {
|
||||||
|
return PGPSecretKeyRing.insertSecretKey(secretKeys, subkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PGPSecretKey secretKeyPlusSignature(PGPSecretKey secretKey, PGPSignature signature) {
|
||||||
|
PGPPublicKey publicKey = secretKey.getPublicKey();
|
||||||
|
publicKey = PGPPublicKey.addCertification(publicKey, signature);
|
||||||
|
PGPSecretKey newSecretKey = PGPSecretKey.replacePublicKey(secretKey, publicKey);
|
||||||
|
return newSecretKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,6 @@ public class SignatureSubpacketGeneratorWrapper
|
||||||
public static SignatureSubpacketGeneratorWrapper createSubpacketsFrom(PGPSignatureSubpacketVector base) {
|
public static SignatureSubpacketGeneratorWrapper createSubpacketsFrom(PGPSignatureSubpacketVector base) {
|
||||||
SignatureSubpacketGeneratorWrapper wrapper = new SignatureSubpacketGeneratorWrapper();
|
SignatureSubpacketGeneratorWrapper wrapper = new SignatureSubpacketGeneratorWrapper();
|
||||||
wrapper.extractSubpacketsFromVector(base);
|
wrapper.extractSubpacketsFromVector(base);
|
||||||
wrapper.setSignatureCreationTime(new Date());
|
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,10 +41,12 @@ import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
import org.pgpainless.algorithm.Feature;
|
import org.pgpainless.algorithm.Feature;
|
||||||
import org.pgpainless.algorithm.HashAlgorithm;
|
import org.pgpainless.algorithm.HashAlgorithm;
|
||||||
import org.pgpainless.algorithm.KeyFlag;
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
|
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||||
import org.pgpainless.algorithm.SignatureSubpacket;
|
import org.pgpainless.algorithm.SignatureSubpacket;
|
||||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import org.pgpainless.key.OpenPgpFingerprint;
|
import org.pgpainless.key.OpenPgpFingerprint;
|
||||||
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
||||||
|
import org.pgpainless.key.generation.type.KeyType;
|
||||||
import org.pgpainless.signature.SignatureUtils;
|
import org.pgpainless.signature.SignatureUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -560,4 +562,58 @@ public final class SignatureSubpacketsUtil {
|
||||||
}
|
}
|
||||||
return (P) allPackets[allPackets.length - 1]; // return last
|
return (P) allPackets[allPackets.length - 1]; // return last
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure that the given key type can carry the given key flags.
|
||||||
|
*
|
||||||
|
* @param type key type
|
||||||
|
* @param flags key flags
|
||||||
|
*/
|
||||||
|
public static void assureKeyCanCarryFlags(KeyType type, KeyFlag... flags) {
|
||||||
|
final int mask = KeyFlag.toBitmask(flags);
|
||||||
|
|
||||||
|
if (!type.canCertify() && KeyFlag.hasKeyFlag(mask, KeyFlag.CERTIFY_OTHER)) {
|
||||||
|
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag CERTIFY_OTHER.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type.canSign() && KeyFlag.hasKeyFlag(mask, KeyFlag.SIGN_DATA)) {
|
||||||
|
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag SIGN_DATA.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type.canEncryptCommunication() && KeyFlag.hasKeyFlag(mask, KeyFlag.ENCRYPT_COMMS)) {
|
||||||
|
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag ENCRYPT_COMMS.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type.canEncryptStorage() && KeyFlag.hasKeyFlag(mask, KeyFlag.ENCRYPT_STORAGE)) {
|
||||||
|
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag ENCRYPT_STORAGE.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type.canAuthenticate() && KeyFlag.hasKeyFlag(mask, KeyFlag.AUTHENTICATION)) {
|
||||||
|
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag AUTHENTIACTION.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assureKeyCanCarryFlags(PublicKeyAlgorithm algorithm, KeyFlag... flags) {
|
||||||
|
final int mask = KeyFlag.toBitmask(flags);
|
||||||
|
|
||||||
|
if (!algorithm.isSigningCapable() && KeyFlag.hasKeyFlag(mask, KeyFlag.CERTIFY_OTHER)) {
|
||||||
|
throw new IllegalArgumentException("Algorithm " + algorithm + " cannot be used with key flag CERTIFY_OTHER.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!algorithm.isSigningCapable() && KeyFlag.hasKeyFlag(mask, KeyFlag.SIGN_DATA)) {
|
||||||
|
throw new IllegalArgumentException("Algorithm " + algorithm + " cannot be used with key flag SIGN_DATA.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!algorithm.isEncryptionCapable() && KeyFlag.hasKeyFlag(mask, KeyFlag.ENCRYPT_COMMS)) {
|
||||||
|
throw new IllegalArgumentException("Algorithm " + algorithm + " cannot be used with key flag ENCRYPT_COMMS.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!algorithm.isEncryptionCapable() && KeyFlag.hasKeyFlag(mask, KeyFlag.ENCRYPT_STORAGE)) {
|
||||||
|
throw new IllegalArgumentException("Algorithm " + algorithm + " cannot be used with key flag ENCRYPT_STORAGE.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!algorithm.isSigningCapable() && KeyFlag.hasKeyFlag(mask, KeyFlag.AUTHENTICATION)) {
|
||||||
|
throw new IllegalArgumentException("Algorithm " + algorithm + " cannot be used with key flag AUTHENTIACTION.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,4 +30,13 @@ public final class CollectionUtils {
|
||||||
System.arraycopy(ts, 0, concat, 1, ts.length);
|
System.arraycopy(ts, 0, concat, 1, ts.length);
|
||||||
return concat;
|
return concat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> boolean contains(T[] ts, T t) {
|
||||||
|
for (T i : ts) {
|
||||||
|
if (i.equals(t)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class GenerateKeys {
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void generateSimpleRSAKey() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
public void generateSimpleRSAKey() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
|
||||||
// Define a primary user-id
|
// Define a primary user-id
|
||||||
String userId = "mpage@pgpainless.org";
|
String userId = "mpage@pgpainless.org";
|
||||||
// Set a password to protect the secret key
|
// Set a password to protect the secret key
|
||||||
|
@ -106,7 +106,6 @@ public class GenerateKeys {
|
||||||
PGPSecretKeyRing secretKey = PGPainless.generateKeyRing()
|
PGPSecretKeyRing secretKey = PGPainless.generateKeyRing()
|
||||||
.simpleRsaKeyRing(userId, RsaLength._4096, password);
|
.simpleRsaKeyRing(userId, RsaLength._4096, password);
|
||||||
|
|
||||||
|
|
||||||
KeyRingInfo keyInfo = new KeyRingInfo(secretKey);
|
KeyRingInfo keyInfo = new KeyRingInfo(secretKey);
|
||||||
assertEquals(1, keyInfo.getSecretKeys().size());
|
assertEquals(1, keyInfo.getSecretKeys().size());
|
||||||
assertEquals(userId, keyInfo.getPrimaryUserId());
|
assertEquals(userId, keyInfo.getPrimaryUserId());
|
||||||
|
|
|
@ -39,7 +39,6 @@ import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureGenerator;
|
import org.bouncycastle.openpgp.PGPSignatureGenerator;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
import org.junit.JUtils;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -493,8 +492,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
// Verify these are not extracted
|
// Verify these are not extracted
|
||||||
assertEquals(0, vector.getIssuerKeyID());
|
assertEquals(0, vector.getIssuerKeyID());
|
||||||
assertNull(vector.getIssuerFingerprint());
|
assertNull(vector.getIssuerFingerprint());
|
||||||
// BC overrides the date with current time
|
assertNull(vector.getSignatureCreationTime());
|
||||||
JUtils.assertDateNotEquals(sigCreationDate, vector.getSignatureCreationTime());
|
|
||||||
|
|
||||||
// Verify these are extracted
|
// Verify these are extracted
|
||||||
assertEquals(256000, vector.getSignatureExpirationTime());
|
assertEquals(256000, vector.getSignatureExpirationTime());
|
||||||
|
|
Loading…
Reference in a new issue