mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-23 03:17:58 +01:00
Refactor KeyRingBuilder
This commit is contained in:
parent
79b04d1535
commit
81c3a471a7
2 changed files with 59 additions and 34 deletions
|
@ -50,4 +50,8 @@ public enum KeyFlag {
|
||||||
}
|
}
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean hasKeyFlag(int mask, KeyFlag flag) {
|
||||||
|
return (mask & flag.getFlag()) == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.sig.KeyFlags;
|
|
||||||
import org.bouncycastle.openpgp.PGPEncryptedData;
|
import org.bouncycastle.openpgp.PGPEncryptedData;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPKeyPair;
|
import org.bouncycastle.openpgp.PGPKeyPair;
|
||||||
|
@ -69,6 +68,7 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
||||||
* @param userId user id.
|
* @param userId user id.
|
||||||
* @param length length in bits.
|
* @param length length in bits.
|
||||||
* @return {@link PGPSecretKeyRing} containing the KeyPair.
|
* @return {@link PGPSecretKeyRing} containing the KeyPair.
|
||||||
|
*
|
||||||
* @throws PGPException
|
* @throws PGPException
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
* @throws InvalidAlgorithmParameterException
|
* @throws InvalidAlgorithmParameterException
|
||||||
|
@ -91,6 +91,7 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
||||||
*
|
*
|
||||||
* @param userId user-id
|
* @param userId user-id
|
||||||
* @return {@link PGPSecretKeyRing} containing the key pairs.
|
* @return {@link PGPSecretKeyRing} containing the key pairs.
|
||||||
|
*
|
||||||
* @throws PGPException
|
* @throws PGPException
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
* @throws InvalidAlgorithmParameterException
|
* @throws InvalidAlgorithmParameterException
|
||||||
|
@ -118,13 +119,18 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithPrimaryUserId withMasterKey(@Nonnull KeySpec spec) {
|
public WithPrimaryUserId withMasterKey(@Nonnull KeySpec spec) {
|
||||||
if ((spec.getSubpackets().getKeyFlags() & KeyFlags.CERTIFY_OTHER) == 0) {
|
if (canCertifyOthers(spec)) {
|
||||||
throw new IllegalArgumentException("Certification Key MUST have KeyFlag CERTIFY_OTHER");
|
throw new IllegalArgumentException("Certification Key MUST have KeyFlag CERTIFY_OTHER");
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyRingBuilder.this.keySpecs.add(0, spec);
|
KeyRingBuilder.this.keySpecs.add(0, spec);
|
||||||
return new WithPrimaryUserIdImpl();
|
return new WithPrimaryUserIdImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean canCertifyOthers(KeySpec keySpec) {
|
||||||
|
return KeyFlag.hasKeyFlag(keySpec.getSubpackets().getKeyFlags(), KeyFlag.CERTIFY_OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
class WithPrimaryUserIdImpl implements WithPrimaryUserId {
|
class WithPrimaryUserIdImpl implements WithPrimaryUserId {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -155,47 +161,42 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
||||||
|
|
||||||
class BuildImpl implements Build {
|
class BuildImpl implements Build {
|
||||||
|
|
||||||
|
private PGPDigestCalculator digestCalculator;
|
||||||
|
private PBESecretKeyEncryptor secretKeyEncryptor;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PGPKeyRing build() throws NoSuchAlgorithmException, PGPException,
|
public PGPKeyRing build() throws NoSuchAlgorithmException, PGPException,
|
||||||
InvalidAlgorithmParameterException {
|
InvalidAlgorithmParameterException {
|
||||||
|
digestCalculator = buildDigestCalculator();
|
||||||
// Hash Calculator
|
secretKeyEncryptor = buildSecretKeyEncryptor();
|
||||||
PGPDigestCalculator calculator = new JcaPGPDigestCalculatorProviderBuilder()
|
|
||||||
.setProvider(ProviderFactory.getProvider())
|
|
||||||
.build()
|
|
||||||
.get(HashAlgorithm.SHA1.getAlgorithmId());
|
|
||||||
|
|
||||||
// Encryptor for encrypting secret keys
|
|
||||||
PBESecretKeyEncryptor encryptor = passphrase == null ?
|
|
||||||
null : // unencrypted key pair, otherwise AES-256 encrypted
|
|
||||||
new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, calculator)
|
|
||||||
.build(passphrase != null ? passphrase.getChars() : null);
|
|
||||||
|
|
||||||
if (passphrase != null) {
|
|
||||||
passphrase.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// First key is the Master Key
|
// First key is the Master Key
|
||||||
KeySpec certKeySpec = keySpecs.get(0);
|
KeySpec certKeySpec = keySpecs.remove(0);
|
||||||
// Remove master key, so that we later only add sub keys.
|
|
||||||
keySpecs.remove(0);
|
|
||||||
|
|
||||||
// Generate Master Key
|
// Generate Master Key
|
||||||
PGPKeyPair certKey = generateKeyPair(certKeySpec);
|
PGPKeyPair certKey = generateKeyPair(certKeySpec);
|
||||||
|
PGPContentSignerBuilder signer = buildContentSigner(certKey);
|
||||||
// Signer for creating self-signature
|
|
||||||
PGPContentSignerBuilder signer = new JcaPGPContentSignerBuilder(
|
|
||||||
certKey.getPublicKey().getAlgorithm(), HashAlgorithm.SHA512.getAlgorithmId())
|
|
||||||
.setProvider(ProviderFactory.getProvider());
|
|
||||||
|
|
||||||
PGPSignatureSubpacketVector hashedSubPackets = certKeySpec.getSubpackets();
|
PGPSignatureSubpacketVector hashedSubPackets = certKeySpec.getSubpackets();
|
||||||
|
|
||||||
// Generator which the user can get the key pair from
|
// Generator which the user can get the key pair from
|
||||||
PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
|
PGPKeyRingGenerator ringGenerator = buildRingGenerator(certKey, signer, hashedSubPackets);
|
||||||
PGPSignature.POSITIVE_CERTIFICATION, certKey,
|
|
||||||
userId, calculator,
|
|
||||||
hashedSubPackets, null, signer, encryptor);
|
|
||||||
|
|
||||||
|
addSubKeys(ringGenerator);
|
||||||
|
|
||||||
|
PGPPublicKeyRing publicKeys = ringGenerator.generatePublicKeyRing();
|
||||||
|
PGPSecretKeyRing secretKeys = ringGenerator.generateSecretKeyRing();
|
||||||
|
|
||||||
|
return new PGPKeyRing(publicKeys, secretKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PGPKeyRingGenerator buildRingGenerator(PGPKeyPair certKey, PGPContentSignerBuilder signer, PGPSignatureSubpacketVector hashedSubPackets) throws PGPException {
|
||||||
|
return new PGPKeyRingGenerator(
|
||||||
|
PGPSignature.POSITIVE_CERTIFICATION, certKey,
|
||||||
|
userId, digestCalculator,
|
||||||
|
hashedSubPackets, null, signer, secretKeyEncryptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSubKeys(PGPKeyRingGenerator ringGenerator) throws NoSuchAlgorithmException, PGPException, InvalidAlgorithmParameterException {
|
||||||
for (KeySpec subKeySpec : keySpecs) {
|
for (KeySpec subKeySpec : keySpecs) {
|
||||||
PGPKeyPair subKey = generateKeyPair(subKeySpec);
|
PGPKeyPair subKey = generateKeyPair(subKeySpec);
|
||||||
if (subKeySpec.isInheritedSubPackets()) {
|
if (subKeySpec.isInheritedSubPackets()) {
|
||||||
|
@ -204,11 +205,31 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
||||||
ringGenerator.addSubKey(subKey, subKeySpec.getSubpackets(), null);
|
ringGenerator.addSubKey(subKey, subKeySpec.getSubpackets(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PGPPublicKeyRing publicKeys = ringGenerator.generatePublicKeyRing();
|
private PGPContentSignerBuilder buildContentSigner(PGPKeyPair certKey) {
|
||||||
PGPSecretKeyRing secretKeys = ringGenerator.generateSecretKeyRing();
|
return new JcaPGPContentSignerBuilder(
|
||||||
|
certKey.getPublicKey().getAlgorithm(), HashAlgorithm.SHA512.getAlgorithmId())
|
||||||
|
.setProvider(ProviderFactory.getProvider());
|
||||||
|
}
|
||||||
|
|
||||||
return new PGPKeyRing(publicKeys, secretKeys);
|
private PBESecretKeyEncryptor buildSecretKeyEncryptor() {
|
||||||
|
PBESecretKeyEncryptor encryptor = passphrase == null ?
|
||||||
|
null : // unencrypted key pair, otherwise AES-256 encrypted
|
||||||
|
new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, digestCalculator)
|
||||||
|
.setProvider(ProviderFactory.getProvider())
|
||||||
|
.build(passphrase.getChars());
|
||||||
|
if (passphrase != null) {
|
||||||
|
passphrase.clear();
|
||||||
|
}
|
||||||
|
return encryptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PGPDigestCalculator buildDigestCalculator() throws PGPException {
|
||||||
|
return new JcaPGPDigestCalculatorProviderBuilder()
|
||||||
|
.setProvider(ProviderFactory.getProvider())
|
||||||
|
.build()
|
||||||
|
.get(HashAlgorithm.SHA1.getAlgorithmId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private PGPKeyPair generateKeyPair(KeySpec spec)
|
private PGPKeyPair generateKeyPair(KeySpec spec)
|
||||||
|
|
Loading…
Reference in a new issue