mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-26 14:22:05 +01:00
Introduce AEADAlgorithmCombination class
This commit is contained in:
parent
8f8b8f534b
commit
678f296b5c
4 changed files with 120 additions and 13 deletions
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,13 +18,12 @@ import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
|
||||||
import org.bouncycastle.bcpg.sig.PrimaryUserID;
|
import org.bouncycastle.bcpg.sig.PrimaryUserID;
|
||||||
import org.bouncycastle.bcpg.sig.RevocationKey;
|
import org.bouncycastle.bcpg.sig.RevocationKey;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.pgpainless.algorithm.AEADAlgorithm;
|
import org.pgpainless.algorithm.AEADAlgorithmCombination;
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
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.SymmetricKeyAlgorithm;
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import org.pgpainless.util.Tuple;
|
|
||||||
|
|
||||||
public interface SelfSignatureSubpackets extends BaseSignatureSubpackets {
|
public interface SelfSignatureSubpackets extends BaseSignatureSubpackets {
|
||||||
|
|
||||||
|
@ -59,11 +58,11 @@ public interface SelfSignatureSubpackets extends BaseSignatureSubpackets {
|
||||||
|
|
||||||
SelfSignatureSubpackets setKeyExpirationTime(@Nullable KeyExpirationTime keyExpirationTime);
|
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);
|
SelfSignatureSubpackets setPreferredAEADCiphersuites(@Nullable PreferredAEADCiphersuites algorithms);
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ import org.bouncycastle.bcpg.sig.TrustSignature;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
import org.pgpainless.algorithm.AEADAlgorithm;
|
import org.pgpainless.algorithm.AEADAlgorithmCombination;
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
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;
|
||||||
|
@ -51,7 +51,6 @@ import org.pgpainless.algorithm.KeyFlag;
|
||||||
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import org.pgpainless.key.util.RevocationAttributes;
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.util.Tuple;
|
|
||||||
|
|
||||||
public class SignatureSubpackets
|
public class SignatureSubpackets
|
||||||
implements BaseSignatureSubpackets, SelfSignatureSubpackets, CertificationSubpackets, RevocationSignatureSubpackets {
|
implements BaseSignatureSubpackets, SelfSignatureSubpackets, CertificationSubpackets, RevocationSignatureSubpackets {
|
||||||
|
@ -318,23 +317,24 @@ public class SignatureSubpackets
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SelfSignatureSubpackets setPreferredAEADCiphersuites(Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>... algorithms) {
|
public SelfSignatureSubpackets setPreferredAEADCiphersuites(AEADAlgorithmCombination... algorithms) {
|
||||||
return setPreferredAEADCiphersuites(new LinkedHashSet<>(Arrays.asList(algorithms)));
|
return setPreferredAEADCiphersuites(new LinkedHashSet<>(Arrays.asList(algorithms)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SelfSignatureSubpackets setPreferredAEADCiphersuites(Set<Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>> algorithms) {
|
public SelfSignatureSubpackets setPreferredAEADCiphersuites(Set<AEADAlgorithmCombination> algorithms) {
|
||||||
return setPreferredAEADCiphersuites(false, algorithms);
|
return setPreferredAEADCiphersuites(false, algorithms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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<>();
|
List<PreferredAEADCiphersuites.Combination> combinations = new ArrayList<>();
|
||||||
Iterator<Tuple<SymmetricKeyAlgorithm, AEADAlgorithm>> iterator = algorithms.iterator();
|
Iterator<AEADAlgorithmCombination> iterator = algorithms.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
Tuple<SymmetricKeyAlgorithm, AEADAlgorithm> tuple = iterator.next();
|
AEADAlgorithmCombination combination = iterator.next();
|
||||||
combinations.add(new PreferredAEADCiphersuites.Combination(
|
combinations.add(new PreferredAEADCiphersuites.Combination(
|
||||||
tuple.getA().getAlgorithmId(), tuple.getB().getAlgorithmId()));
|
combination.getSymmetricKeyAlgorithm().getAlgorithmId(),
|
||||||
|
combination.getAeadAlgorithm().getAlgorithmId()));
|
||||||
}
|
}
|
||||||
PreferredAEADCiphersuites subpacket = new PreferredAEADCiphersuites(
|
PreferredAEADCiphersuites subpacket = new PreferredAEADCiphersuites(
|
||||||
isCritical, combinations.toArray(new PreferredAEADCiphersuites.Combination[0]));
|
isCritical, combinations.toArray(new PreferredAEADCiphersuites.Combination[0]));
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.bouncycastle.bcpg.sig.IssuerKeyID;
|
||||||
import org.bouncycastle.bcpg.sig.KeyExpirationTime;
|
import org.bouncycastle.bcpg.sig.KeyExpirationTime;
|
||||||
import org.bouncycastle.bcpg.sig.KeyFlags;
|
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||||
import org.bouncycastle.bcpg.sig.NotationData;
|
import org.bouncycastle.bcpg.sig.NotationData;
|
||||||
|
import org.bouncycastle.bcpg.sig.PreferredAEADCiphersuites;
|
||||||
import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
|
import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
|
||||||
import org.bouncycastle.bcpg.sig.PrimaryUserID;
|
import org.bouncycastle.bcpg.sig.PrimaryUserID;
|
||||||
import org.bouncycastle.bcpg.sig.RegularExpression;
|
import org.bouncycastle.bcpg.sig.RegularExpression;
|
||||||
|
@ -37,6 +38,7 @@ import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureList;
|
import org.bouncycastle.openpgp.PGPSignatureList;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
|
import org.pgpainless.algorithm.AEADAlgorithmCombination;
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
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;
|
||||||
|
@ -334,6 +336,39 @@ public final class SignatureSubpacketsUtil {
|
||||||
return algorithms;
|
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.
|
* Return the primary user-id subpacket from the signatures hashed area.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue