Introduce AEADAlgorithmCombination class

This commit is contained in:
Paul Schaub 2023-08-03 14:42:35 +02:00
parent 8f8b8f534b
commit 678f296b5c
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
4 changed files with 120 additions and 13 deletions

View File

@ -0,0 +1,73 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.algorithm;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bouncycastle.bcpg.sig.PreferredAEADCiphersuites;
public final class AEADAlgorithmCombination {
private final AEADAlgorithm aeadAlgorithm;
private final SymmetricKeyAlgorithm symmetricKeyAlgorithm;
/**
* AES-128 + OCB is a MUST implement and is therefore implicitly supported.
*
* @see <a href="https://openpgp-wg.gitlab.io/rfc4880bis/#name-preferred-aead-ciphersuites">
* Crypto-Refresh § 5.2.3.15. Preferred AEAD Ciphersuites</a>
*/
public static AEADAlgorithmCombination AES_128_OCB = AEADAlgorithmCombination.from(
SymmetricKeyAlgorithm.AES_128, AEADAlgorithm.OCB);
private AEADAlgorithmCombination(@Nonnull SymmetricKeyAlgorithm symmetricKeyAlgorithm,
@Nonnull AEADAlgorithm aeadAlgorithm) {
this.aeadAlgorithm = aeadAlgorithm;
this.symmetricKeyAlgorithm = symmetricKeyAlgorithm;
}
@Nonnull
public AEADAlgorithm getAeadAlgorithm() {
return aeadAlgorithm;
}
@Nonnull
public SymmetricKeyAlgorithm getSymmetricKeyAlgorithm() {
return symmetricKeyAlgorithm;
}
public static AEADAlgorithmCombination from(@Nonnull SymmetricKeyAlgorithm symmetricKeyAlgorithm,
@Nonnull AEADAlgorithm aeadAlgorithm) {
return new AEADAlgorithmCombination(symmetricKeyAlgorithm, aeadAlgorithm);
}
@Nullable
public static AEADAlgorithmCombination from(PreferredAEADCiphersuites.Combination combination) {
return fromIds(combination.getSymmetricAlgorithm(), combination.getAeadAlgorithm());
}
@Nonnull
public static AEADAlgorithmCombination requireFrom(PreferredAEADCiphersuites.Combination combination) {
return requireFromIds(combination.getSymmetricAlgorithm(), combination.getAeadAlgorithm());
}
@Nullable
public static AEADAlgorithmCombination fromIds(int symmetricAlgorithmId, int aeadAlgorithmId) {
SymmetricKeyAlgorithm symmetric = SymmetricKeyAlgorithm.fromId(symmetricAlgorithmId);
AEADAlgorithm aead = AEADAlgorithm.fromId(aeadAlgorithmId);
if (symmetric == null || aead == null) {
return null;
}
return new AEADAlgorithmCombination(symmetric, aead);
}
@Nonnull
public static AEADAlgorithmCombination requireFromIds(int symmetricAlgorithmId, int aeadAlgorithmId) {
return from(SymmetricKeyAlgorithm.requireFromId(symmetricAlgorithmId), AEADAlgorithm.requireFromId(aeadAlgorithmId));
}
}

View File

@ -18,13 +18,12 @@ import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
import org.bouncycastle.bcpg.sig.PrimaryUserID;
import org.bouncycastle.bcpg.sig.RevocationKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.pgpainless.algorithm.AEADAlgorithm;
import org.pgpainless.algorithm.AEADAlgorithmCombination;
import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.Feature;
import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.util.Tuple;
public interface SelfSignatureSubpackets extends BaseSignatureSubpackets {
@ -59,11 +58,11 @@ public interface SelfSignatureSubpackets extends BaseSignatureSubpackets {
SelfSignatureSubpackets setKeyExpirationTime(@Nullable KeyExpirationTime keyExpirationTime);
SelfSignatureSubpackets setPreferredAEADCiphersuites(Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>... algorithms);
SelfSignatureSubpackets setPreferredAEADCiphersuites(AEADAlgorithmCombination... algorithms);
SelfSignatureSubpackets setPreferredAEADCiphersuites(Set<Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>> algorithms);
SelfSignatureSubpackets setPreferredAEADCiphersuites(Set<AEADAlgorithmCombination> algorithms);
SelfSignatureSubpackets setPreferredAEADCiphersuites(boolean isCritical, Set<Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>> algorithms);
SelfSignatureSubpackets setPreferredAEADCiphersuites(boolean isCritical, Set<AEADAlgorithmCombination> algorithms);
SelfSignatureSubpackets setPreferredAEADCiphersuites(@Nullable PreferredAEADCiphersuites algorithms);

View File

@ -43,7 +43,7 @@ import org.bouncycastle.bcpg.sig.TrustSignature;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
import org.pgpainless.algorithm.AEADAlgorithm;
import org.pgpainless.algorithm.AEADAlgorithmCombination;
import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.Feature;
import org.pgpainless.algorithm.HashAlgorithm;
@ -51,7 +51,6 @@ import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.PublicKeyAlgorithm;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.key.util.RevocationAttributes;
import org.pgpainless.util.Tuple;
public class SignatureSubpackets
implements BaseSignatureSubpackets, SelfSignatureSubpackets, CertificationSubpackets, RevocationSignatureSubpackets {
@ -318,23 +317,24 @@ public class SignatureSubpackets
}
@Override
public SelfSignatureSubpackets setPreferredAEADCiphersuites(Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>... algorithms) {
public SelfSignatureSubpackets setPreferredAEADCiphersuites(AEADAlgorithmCombination... algorithms) {
return setPreferredAEADCiphersuites(new LinkedHashSet<>(Arrays.asList(algorithms)));
}
@Override
public SelfSignatureSubpackets setPreferredAEADCiphersuites(Set<Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>> algorithms) {
public SelfSignatureSubpackets setPreferredAEADCiphersuites(Set<AEADAlgorithmCombination> algorithms) {
return setPreferredAEADCiphersuites(false, algorithms);
}
@Override
public SelfSignatureSubpackets setPreferredAEADCiphersuites(boolean isCritical, Set<Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>> algorithms) {
public SelfSignatureSubpackets setPreferredAEADCiphersuites(boolean isCritical, Set<AEADAlgorithmCombination> algorithms) {
List<PreferredAEADCiphersuites.Combination> combinations = new ArrayList<>();
Iterator<Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>> iterator = algorithms.iterator();
Iterator<AEADAlgorithmCombination> iterator = algorithms.iterator();
while (iterator.hasNext()) {
Tuple<SymmetricKeyAlgorithm, AEADAlgorithm> tuple = iterator.next();
AEADAlgorithmCombination combination = iterator.next();
combinations.add(new PreferredAEADCiphersuites.Combination(
tuple.getA().getAlgorithmId(), tuple.getB().getAlgorithmId()));
combination.getSymmetricKeyAlgorithm().getAlgorithmId(),
combination.getAeadAlgorithm().getAlgorithmId()));
}
PreferredAEADCiphersuites subpacket = new PreferredAEADCiphersuites(
isCritical, combinations.toArray(new PreferredAEADCiphersuites.Combination[0]));

View File

@ -21,6 +21,7 @@ import org.bouncycastle.bcpg.sig.IssuerKeyID;
import org.bouncycastle.bcpg.sig.KeyExpirationTime;
import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.bcpg.sig.NotationData;
import org.bouncycastle.bcpg.sig.PreferredAEADCiphersuites;
import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
import org.bouncycastle.bcpg.sig.PrimaryUserID;
import org.bouncycastle.bcpg.sig.RegularExpression;
@ -37,6 +38,7 @@ import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureList;
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
import org.pgpainless.algorithm.AEADAlgorithmCombination;
import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.Feature;
import org.pgpainless.algorithm.HashAlgorithm;
@ -334,6 +336,39 @@ public final class SignatureSubpacketsUtil {
return algorithms;
}
public static @Nullable PreferredAEADCiphersuites getPreferredAEADAlgorithms(PGPSignature signature) {
org.bouncycastle.bcpg.SignatureSubpacket subpacket = hashed(signature, SignatureSubpacket.preferredAEADAlgorithms);
if (subpacket == null) {
return null;
}
// Workaround for https://github.com/pgpainless/pgpainless/pull/399
// TODO: Remove when BC 1.77 is released
if (subpacket instanceof PreferredAlgorithms) {
List<PreferredAEADCiphersuites.Combination> combinationList = new ArrayList<>();
int[] algorithms = ((PreferredAlgorithms) subpacket).getPreferences();
for (int i = 0; i < algorithms.length; i += 2) {
combinationList.add(new PreferredAEADCiphersuites.Combination(algorithms[i], algorithms[i + 1]));
}
PreferredAEADCiphersuites aead = new PreferredAEADCiphersuites(
subpacket.isCritical(), combinationList.toArray(new PreferredAEADCiphersuites.Combination[0]));
return aead;
}
return (PreferredAEADCiphersuites) subpacket;
}
public static @Nonnull Set<AEADAlgorithmCombination> parsePreferredAEADAlgorithms(PGPSignature signature) {
Set<AEADAlgorithmCombination> algorithms = new LinkedHashSet<>();
PreferredAEADCiphersuites preferences = getPreferredAEADAlgorithms(signature);
if (preferences != null) {
for (PreferredAEADCiphersuites.Combination combination : preferences.getAlgorithms()) {
algorithms.add(AEADAlgorithmCombination.from(combination));
}
}
return algorithms;
}
/**
* Return the primary user-id subpacket from the signatures hashed area.
*