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

Further refactoring of KeyRingBuilder

This commit is contained in:
Paul Schaub 2020-01-12 16:37:24 +01:00
parent 81c3a471a7
commit 8a2051904a
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
4 changed files with 77 additions and 19 deletions

View file

@ -51,7 +51,15 @@ public enum KeyFlag {
return flags; return flags;
} }
public static int toBitmask(KeyFlag... flags) {
int mask = 0;
for (KeyFlag f : flags) {
mask |= f.getFlag();
}
return mask;
}
public static boolean hasKeyFlag(int mask, KeyFlag flag) { public static boolean hasKeyFlag(int mask, KeyFlag flag) {
return (mask & flag.getFlag()) == 0; return (mask & flag.getFlag()) == flag.getFlag();
} }
} }

View file

@ -75,7 +75,8 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
*/ */
public PGPKeyRing simpleRsaKeyRing(@Nonnull String userId, @Nonnull RsaLength length) public PGPKeyRing simpleRsaKeyRing(@Nonnull String userId, @Nonnull RsaLength length)
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
return withMasterKey( return this
.withMasterKey(
KeySpec.getBuilder(RSA_GENERAL.withLength(length)) KeySpec.getBuilder(RSA_GENERAL.withLength(length))
.withDefaultKeyFlags() .withDefaultKeyFlags()
.withDefaultAlgorithms()) .withDefaultAlgorithms())
@ -98,7 +99,8 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
*/ */
public PGPKeyRing simpleEcKeyRing(@Nonnull String userId) public PGPKeyRing simpleEcKeyRing(@Nonnull String userId)
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
return withSubKey( return this
.withSubKey(
KeySpec.getBuilder(ECDH.fromCurve(EllipticCurve._P256)) KeySpec.getBuilder(ECDH.fromCurve(EllipticCurve._P256))
.withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS) .withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)
.withDefaultAlgorithms()) .withDefaultAlgorithms())
@ -119,16 +121,21 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
@Override @Override
public WithPrimaryUserId withMasterKey(@Nonnull KeySpec spec) { public WithPrimaryUserId withMasterKey(@Nonnull KeySpec spec) {
if (canCertifyOthers(spec)) { verifyMasterKeyCanCertify(spec);
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 void verifyMasterKeyCanCertify(KeySpec spec) {
if (!canCertifyOthers(spec)) {
throw new IllegalArgumentException("Certification Key MUST have KeyFlag CERTIFY_OTHER");
}
}
private boolean canCertifyOthers(KeySpec keySpec) { private boolean canCertifyOthers(KeySpec keySpec) {
return KeyFlag.hasKeyFlag(keySpec.getSubpackets().getKeyFlags(), KeyFlag.CERTIFY_OTHER); int flags = keySpec.getSubpackets().getKeyFlags();
return KeyFlag.hasKeyFlag(flags, KeyFlag.CERTIFY_OTHER);
} }
class WithPrimaryUserIdImpl implements WithPrimaryUserId { class WithPrimaryUserIdImpl implements WithPrimaryUserId {
@ -189,14 +196,18 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
return new PGPKeyRing(publicKeys, secretKeys); return new PGPKeyRing(publicKeys, secretKeys);
} }
private PGPKeyRingGenerator buildRingGenerator(PGPKeyPair certKey, PGPContentSignerBuilder signer, PGPSignatureSubpacketVector hashedSubPackets) throws PGPException { private PGPKeyRingGenerator buildRingGenerator(PGPKeyPair certKey,
PGPContentSignerBuilder signer,
PGPSignatureSubpacketVector hashedSubPackets)
throws PGPException {
return new PGPKeyRingGenerator( return new PGPKeyRingGenerator(
PGPSignature.POSITIVE_CERTIFICATION, certKey, PGPSignature.POSITIVE_CERTIFICATION, certKey,
userId, digestCalculator, userId, digestCalculator,
hashedSubPackets, null, signer, secretKeyEncryptor); hashedSubPackets, null, signer, secretKeyEncryptor);
} }
private void addSubKeys(PGPKeyRingGenerator ringGenerator) throws NoSuchAlgorithmException, PGPException, InvalidAlgorithmParameterException { 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()) {
@ -209,8 +220,8 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
private PGPContentSignerBuilder buildContentSigner(PGPKeyPair certKey) { private PGPContentSignerBuilder buildContentSigner(PGPKeyPair certKey) {
return new JcaPGPContentSignerBuilder( return new JcaPGPContentSignerBuilder(
certKey.getPublicKey().getAlgorithm(), HashAlgorithm.SHA512.getAlgorithmId()) certKey.getPublicKey().getAlgorithm(), HashAlgorithm.SHA512.getAlgorithmId())
.setProvider(ProviderFactory.getProvider()); .setProvider(ProviderFactory.getProvider());
} }
private PBESecretKeyEncryptor buildSecretKeyEncryptor() { private PBESecretKeyEncryptor buildSecretKeyEncryptor() {

View file

@ -38,11 +38,7 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
@Override @Override
public WithDetailedConfiguration withKeyFlags(@Nonnull KeyFlag... flags) { public WithDetailedConfiguration withKeyFlags(@Nonnull KeyFlag... flags) {
int val = 0; this.hashedSubPackets.setKeyFlags(false, KeyFlag.toBitmask(flags));
for (KeyFlag f : flags) {
val |= f.getFlag();
}
this.hashedSubPackets.setKeyFlags(false, val);
return new WithDetailedConfigurationImpl(); return new WithDetailedConfigurationImpl();
} }

View file

@ -0,0 +1,43 @@
/*
* Copyright 2020 Paul Schaub.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.pgpainless.key;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;
import java.util.Arrays;
import org.junit.Test;
import org.pgpainless.algorithm.KeyFlag;
public class KeyFlagTest {
@Test
public void hasKeyFlagTest() {
int mask = KeyFlag.toBitmask(KeyFlag.AUTHENTICATION, KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA);
assertEquals(0x23, mask);
assertEquals(Arrays.asList(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.AUTHENTICATION),
KeyFlag.fromBitmask(mask));
assertTrue(KeyFlag.hasKeyFlag(mask, KeyFlag.CERTIFY_OTHER));
assertTrue(KeyFlag.hasKeyFlag(mask, KeyFlag.AUTHENTICATION));
assertTrue(KeyFlag.hasKeyFlag(mask, KeyFlag.SIGN_DATA));
assertFalse(KeyFlag.hasKeyFlag(mask, KeyFlag.ENCRYPT_STORAGE));
assertFalse(KeyFlag.hasKeyFlag(mask, KeyFlag.SHARED));
}
}