001// SPDX-FileCopyrightText: 2018 Paul Schaub <vanitasvitae@fsfe.org> 002// 003// SPDX-License-Identifier: Apache-2.0 004 005package org.pgpainless.encryption_signing; 006 007import java.io.IOException; 008import java.io.OutputStream; 009import java.util.ArrayList; 010import java.util.List; 011import java.util.Set; 012import javax.annotation.Nonnull; 013 014import org.bouncycastle.openpgp.PGPException; 015import org.pgpainless.PGPainless; 016import org.pgpainless.algorithm.CompressionAlgorithm; 017import org.pgpainless.algorithm.SymmetricKeyAlgorithm; 018import org.pgpainless.algorithm.negotiation.SymmetricKeyAlgorithmNegotiator; 019import org.pgpainless.key.SubkeyIdentifier; 020import org.slf4j.Logger; 021import org.slf4j.LoggerFactory; 022 023public class EncryptionBuilder implements EncryptionBuilderInterface { 024 025 private static final Logger LOGGER = LoggerFactory.getLogger(EncryptionBuilder.class); 026 027 private OutputStream outputStream; 028 029 @Override 030 public WithOptions onOutputStream(@Nonnull OutputStream outputStream) { 031 this.outputStream = outputStream; 032 return new WithOptionsImpl(); 033 } 034 035 class WithOptionsImpl implements WithOptions { 036 @Override 037 public EncryptionStream withOptions(ProducerOptions options) throws PGPException, IOException { 038 if (options == null) { 039 throw new NullPointerException("ProducerOptions cannot be null."); 040 } 041 return new EncryptionStream(outputStream, options); 042 } 043 } 044 045 /** 046 * Negotiate the {@link SymmetricKeyAlgorithm} used for message encryption. 047 * 048 * @param encryptionOptions encryption options 049 * @return negotiated symmetric key algorithm 050 */ 051 public static SymmetricKeyAlgorithm negotiateSymmetricEncryptionAlgorithm(EncryptionOptions encryptionOptions) { 052 List<Set<SymmetricKeyAlgorithm>> preferences = new ArrayList<>(); 053 for (SubkeyIdentifier key : encryptionOptions.getKeyViews().keySet()) { 054 preferences.add(encryptionOptions.getKeyViews().get(key).getPreferredSymmetricKeyAlgorithms()); 055 } 056 057 SymmetricKeyAlgorithm algorithm = SymmetricKeyAlgorithmNegotiator 058 .byPopularity() 059 .negotiate( 060 PGPainless.getPolicy().getSymmetricKeyEncryptionAlgorithmPolicy(), 061 encryptionOptions.getEncryptionAlgorithmOverride(), 062 preferences); 063 LOGGER.debug("Negotiation resulted in {} being the symmetric encryption algorithm of choice.", algorithm); 064 return algorithm; 065 } 066 067 public static CompressionAlgorithm negotiateCompressionAlgorithm(ProducerOptions producerOptions) { 068 CompressionAlgorithm compressionAlgorithmOverride = producerOptions.getCompressionAlgorithmOverride(); 069 if (compressionAlgorithmOverride != null) { 070 return compressionAlgorithmOverride; 071 } 072 073 // TODO: Negotiation 074 075 return PGPainless.getPolicy().getCompressionAlgorithmPolicy().defaultCompressionAlgorithm(); 076 } 077}