From 601e635604ab3843ef24d25f786dbbab6a1a603d Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Fri, 4 Aug 2023 13:50:30 +0200 Subject: [PATCH] Add AEAD algorithms to AlgorithmSuite and allow setting / overriding preferrences in KeySpecBuilder --- .../algorithm/AEADAlgorithmCombination.java | 9 ++- .../pgpainless/algorithm/AlgorithmSuite.java | 80 ++++++++++++++----- .../key/generation/KeySpecBuilder.java | 10 +++ .../generation/KeySpecBuilderInterface.java | 3 + 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/pgpainless-core/src/main/java/org/pgpainless/algorithm/AEADAlgorithmCombination.java b/pgpainless-core/src/main/java/org/pgpainless/algorithm/AEADAlgorithmCombination.java index 538e2795..362dd26b 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/algorithm/AEADAlgorithmCombination.java +++ b/pgpainless-core/src/main/java/org/pgpainless/algorithm/AEADAlgorithmCombination.java @@ -26,7 +26,14 @@ public final class AEADAlgorithmCombination { private AEADAlgorithmCombination(@Nonnull SymmetricKeyAlgorithm symmetricKeyAlgorithm, @Nonnull AEADAlgorithm aeadAlgorithm) { this.aeadAlgorithm = aeadAlgorithm; - this.symmetricKeyAlgorithm = symmetricKeyAlgorithm; + this.symmetricKeyAlgorithm = requireNotUnencrypted(symmetricKeyAlgorithm); + } + + private static SymmetricKeyAlgorithm requireNotUnencrypted(SymmetricKeyAlgorithm algorithm) { + if (algorithm == SymmetricKeyAlgorithm.NULL) { + throw new IllegalArgumentException("Symmetric Key Algorithm MUST NOT be NULL (unencrypted)."); + } + return algorithm; } @Nonnull diff --git a/pgpainless-core/src/main/java/org/pgpainless/algorithm/AlgorithmSuite.java b/pgpainless-core/src/main/java/org/pgpainless/algorithm/AlgorithmSuite.java index e155e367..944aacd8 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/algorithm/AlgorithmSuite.java +++ b/pgpainless-core/src/main/java/org/pgpainless/algorithm/AlgorithmSuite.java @@ -4,6 +4,7 @@ package org.pgpainless.algorithm; +import javax.annotation.Nonnull; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; @@ -16,33 +17,71 @@ import java.util.Set; */ public class AlgorithmSuite { + private static final List defaultSymmetricAlgorithms = Arrays.asList( + SymmetricKeyAlgorithm.AES_256, + SymmetricKeyAlgorithm.AES_192, + SymmetricKeyAlgorithm.AES_128); + private static final List defaultHashAlgorithms = Arrays.asList( + HashAlgorithm.SHA512, + HashAlgorithm.SHA384, + HashAlgorithm.SHA256, + HashAlgorithm.SHA224); + private static final List defaultCompressionAlgorithms = Arrays.asList( + CompressionAlgorithm.ZLIB, + CompressionAlgorithm.BZIP2, + CompressionAlgorithm.ZIP, + CompressionAlgorithm.UNCOMPRESSED); + private static final List defaultAEADAlgorithms = Arrays.asList( + AEADAlgorithmCombination.from(SymmetricKeyAlgorithm.AES_256, AEADAlgorithm.OCB), + AEADAlgorithmCombination.from(SymmetricKeyAlgorithm.AES_256, AEADAlgorithm.EAX), + AEADAlgorithmCombination.from(SymmetricKeyAlgorithm.AES_256, AEADAlgorithm.GCM), + AEADAlgorithmCombination.from(SymmetricKeyAlgorithm.AES_192, AEADAlgorithm.OCB), + AEADAlgorithmCombination.from(SymmetricKeyAlgorithm.AES_192, AEADAlgorithm.EAX), + AEADAlgorithmCombination.from(SymmetricKeyAlgorithm.AES_192, AEADAlgorithm.GCM), + AEADAlgorithmCombination.from(SymmetricKeyAlgorithm.AES_128, AEADAlgorithm.OCB), + AEADAlgorithmCombination.from(SymmetricKeyAlgorithm.AES_128, AEADAlgorithm.EAX), + AEADAlgorithmCombination.from(SymmetricKeyAlgorithm.AES_128, AEADAlgorithm.GCM)); private static final AlgorithmSuite defaultAlgorithmSuite = new AlgorithmSuite( - Arrays.asList( - SymmetricKeyAlgorithm.AES_256, - SymmetricKeyAlgorithm.AES_192, - SymmetricKeyAlgorithm.AES_128), - Arrays.asList( - HashAlgorithm.SHA512, - HashAlgorithm.SHA384, - HashAlgorithm.SHA256, - HashAlgorithm.SHA224), - Arrays.asList( - CompressionAlgorithm.ZLIB, - CompressionAlgorithm.BZIP2, - CompressionAlgorithm.ZIP, - CompressionAlgorithm.UNCOMPRESSED) - ); + defaultSymmetricAlgorithms, + defaultHashAlgorithms, + defaultCompressionAlgorithms, + defaultAEADAlgorithms); private final Set symmetricKeyAlgorithms; private final Set hashAlgorithms; private final Set compressionAlgorithms; + private final Set aeadAlgorithms; - public AlgorithmSuite(List symmetricKeyAlgorithms, - List hashAlgorithms, - List compressionAlgorithms) { + /** + * Create a new AlgorithmSuite. + * + * @deprecated use {@link AlgorithmSuite#AlgorithmSuite(List, List, List, List)} instead. + * @param symmetricKeyAlgorithms preferred symmetric algorithms + * @param hashAlgorithms preferred hash algorithms + * @param compressionAlgorithms preferred compression algorithms + */ + @Deprecated + public AlgorithmSuite(@Nonnull List symmetricKeyAlgorithms, + @Nonnull List hashAlgorithms, + @Nonnull List compressionAlgorithms) { + this(symmetricKeyAlgorithms, hashAlgorithms, compressionAlgorithms, defaultAEADAlgorithms); + } + + /** + * Create a new AlgorithmSuite. + * @param symmetricKeyAlgorithms preferred symmetric algorithms + * @param hashAlgorithms preferred hash algorithms + * @param compressionAlgorithms preferred compression algorithms + * @param aeadAlgorithms preferred AEAD algorithm combinations + */ + public AlgorithmSuite(@Nonnull List symmetricKeyAlgorithms, + @Nonnull List hashAlgorithms, + @Nonnull List compressionAlgorithms, + @Nonnull List aeadAlgorithms) { this.symmetricKeyAlgorithms = Collections.unmodifiableSet(new LinkedHashSet<>(symmetricKeyAlgorithms)); this.hashAlgorithms = Collections.unmodifiableSet(new LinkedHashSet<>(hashAlgorithms)); this.compressionAlgorithms = Collections.unmodifiableSet(new LinkedHashSet<>(compressionAlgorithms)); + this.aeadAlgorithms = Collections.unmodifiableSet(new LinkedHashSet<>(aeadAlgorithms)); } public Set getSymmetricKeyAlgorithms() { @@ -57,7 +96,12 @@ public class AlgorithmSuite { return new LinkedHashSet<>(compressionAlgorithms); } + public Set getAEADAlgorithms() { + return new LinkedHashSet<>(aeadAlgorithms); + } + public static AlgorithmSuite getDefaultAlgorithmSuite() { return defaultAlgorithmSuite; } + } diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeySpecBuilder.java b/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeySpecBuilder.java index 559dd3ce..1c6af5ce 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeySpecBuilder.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeySpecBuilder.java @@ -11,6 +11,7 @@ import java.util.Set; import javax.annotation.Nonnull; import org.pgpainless.PGPainless; +import org.pgpainless.algorithm.AEADAlgorithmCombination; import org.pgpainless.algorithm.AlgorithmSuite; import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.Feature; @@ -32,6 +33,7 @@ public class KeySpecBuilder implements KeySpecBuilderInterface { private Set preferredCompressionAlgorithms = algorithmSuite.getCompressionAlgorithms(); private Set preferredHashAlgorithms = algorithmSuite.getHashAlgorithms(); private Set preferredSymmetricAlgorithms = algorithmSuite.getSymmetricKeyAlgorithms(); + private Set preferredAEADAlgorithms = algorithmSuite.getAEADAlgorithms(); private Date keyCreationDate; KeySpecBuilder(@Nonnull KeyType type, KeyFlag flag, KeyFlag... flags) { @@ -73,6 +75,13 @@ public class KeySpecBuilder implements KeySpecBuilderInterface { return this; } + @Override + public KeySpecBuilder overridePreferredAEADAlgorithms( + @Nonnull AEADAlgorithmCombination... preferredAEADAlgorithms) { + this.preferredAEADAlgorithms = new LinkedHashSet<>(Arrays.asList(preferredAEADAlgorithms)); + return this; + } + @Override public KeySpecBuilder setKeyCreationDate(@Nonnull Date creationDate) { this.keyCreationDate = creationDate; @@ -85,6 +94,7 @@ public class KeySpecBuilder implements KeySpecBuilderInterface { this.hashedSubpackets.setPreferredCompressionAlgorithms(preferredCompressionAlgorithms); this.hashedSubpackets.setPreferredHashAlgorithms(preferredHashAlgorithms); this.hashedSubpackets.setPreferredSymmetricKeyAlgorithms(preferredSymmetricAlgorithms); + this.hashedSubpackets.setPreferredAEADCiphersuites(preferredAEADAlgorithms); this.hashedSubpackets.setFeatures(Feature.MODIFICATION_DETECTION); return new KeySpec(type, (SignatureSubpackets) hashedSubpackets, false, keyCreationDate); diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeySpecBuilderInterface.java b/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeySpecBuilderInterface.java index 4a99bc8d..4d73165c 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeySpecBuilderInterface.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeySpecBuilderInterface.java @@ -6,6 +6,7 @@ package org.pgpainless.key.generation; import javax.annotation.Nonnull; +import org.pgpainless.algorithm.AEADAlgorithmCombination; import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.HashAlgorithm; import org.pgpainless.algorithm.SymmetricKeyAlgorithm; @@ -20,6 +21,8 @@ public interface KeySpecBuilderInterface { KeySpecBuilder overridePreferredSymmetricKeyAlgorithms(@Nonnull SymmetricKeyAlgorithm... preferredSymmetricKeyAlgorithms); + KeySpecBuilder overridePreferredAEADAlgorithms(@Nonnull AEADAlgorithmCombination... preferredAEADAlgorithms); + KeySpecBuilder setKeyCreationDate(@Nonnull Date creationDate); KeySpec build();