001// SPDX-FileCopyrightText: 2018 Paul Schaub <vanitasvitae@fsfe.org> 002// 003// SPDX-License-Identifier: Apache-2.0 004 005package org.pgpainless.key.generation; 006 007import java.util.Arrays; 008import java.util.LinkedHashSet; 009import java.util.Set; 010import javax.annotation.Nonnull; 011 012import org.pgpainless.PGPainless; 013import org.pgpainless.algorithm.AlgorithmSuite; 014import org.pgpainless.algorithm.CompressionAlgorithm; 015import org.pgpainless.algorithm.Feature; 016import org.pgpainless.algorithm.HashAlgorithm; 017import org.pgpainless.algorithm.KeyFlag; 018import org.pgpainless.algorithm.SymmetricKeyAlgorithm; 019import org.pgpainless.key.generation.type.KeyType; 020import org.pgpainless.signature.subpackets.SelfSignatureSubpackets; 021import org.pgpainless.signature.subpackets.SignatureSubpackets; 022import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil; 023import org.pgpainless.util.CollectionUtils; 024 025public class KeySpecBuilder implements KeySpecBuilderInterface { 026 027 private final KeyType type; 028 private final KeyFlag[] keyFlags; 029 private final SelfSignatureSubpackets hashedSubpackets = new SignatureSubpackets(); 030 private final AlgorithmSuite algorithmSuite = PGPainless.getPolicy().getKeyGenerationAlgorithmSuite(); 031 private Set<CompressionAlgorithm> preferredCompressionAlgorithms = algorithmSuite.getCompressionAlgorithms(); 032 private Set<HashAlgorithm> preferredHashAlgorithms = algorithmSuite.getHashAlgorithms(); 033 private Set<SymmetricKeyAlgorithm> preferredSymmetricAlgorithms = algorithmSuite.getSymmetricKeyAlgorithms(); 034 035 KeySpecBuilder(@Nonnull KeyType type, KeyFlag flag, KeyFlag... flags) { 036 if (flag == null) { 037 throw new IllegalArgumentException("Key MUST carry at least one key flag"); 038 } 039 if (flags == null) { 040 throw new IllegalArgumentException("List of additional flags MUST NOT be null."); 041 } 042 flags = CollectionUtils.concat(flag, flags); 043 SignatureSubpacketsUtil.assureKeyCanCarryFlags(type, flags); 044 this.type = type; 045 this.keyFlags = flags; 046 } 047 048 @Override 049 public KeySpecBuilder overridePreferredCompressionAlgorithms( 050 @Nonnull CompressionAlgorithm... compressionAlgorithms) { 051 this.preferredCompressionAlgorithms = new LinkedHashSet<>(Arrays.asList(compressionAlgorithms)); 052 return this; 053 } 054 055 @Override 056 public KeySpecBuilder overridePreferredHashAlgorithms( 057 @Nonnull HashAlgorithm... preferredHashAlgorithms) { 058 this.preferredHashAlgorithms = new LinkedHashSet<>(Arrays.asList(preferredHashAlgorithms)); 059 return this; 060 } 061 062 @Override 063 public KeySpecBuilder overridePreferredSymmetricKeyAlgorithms( 064 @Nonnull SymmetricKeyAlgorithm... preferredSymmetricKeyAlgorithms) { 065 this.preferredSymmetricAlgorithms = new LinkedHashSet<>(Arrays.asList(preferredSymmetricKeyAlgorithms)); 066 return this; 067 } 068 069 070 @Override 071 public KeySpec build() { 072 this.hashedSubpackets.setKeyFlags(keyFlags); 073 this.hashedSubpackets.setPreferredCompressionAlgorithms(preferredCompressionAlgorithms); 074 this.hashedSubpackets.setPreferredHashAlgorithms(preferredHashAlgorithms); 075 this.hashedSubpackets.setPreferredSymmetricKeyAlgorithms(preferredSymmetricAlgorithms); 076 this.hashedSubpackets.setFeatures(Feature.MODIFICATION_DETECTION); 077 078 return new KeySpec(type, (SignatureSubpackets) hashedSubpackets, false); 079 } 080}