// SPDX-FileCopyrightText: 2023 Paul Schaub // // SPDX-License-Identifier: Apache-2.0 package org.pgpainless.algorithm.negotiation import java.lang.IllegalArgumentException import org.pgpainless.algorithm.SymmetricKeyAlgorithm import org.pgpainless.policy.Policy interface SymmetricKeyAlgorithmNegotiator { /** * Negotiate a symmetric encryption algorithm. If the override is non-null, it will be returned * instead of performing an actual negotiation. Otherwise, the list of ordered sets containing * the preferences of different recipient keys will be used to determine a suitable symmetric * encryption algorithm. * * @param policy algorithm policy * @param override algorithm override (if not null, return this) * @param keyPreferences list of preferences per key * @return negotiated algorithm */ fun negotiate( policy: Policy.SymmetricKeyAlgorithmPolicy, override: SymmetricKeyAlgorithm?, keyPreferences: List> ): SymmetricKeyAlgorithm companion object { @JvmStatic fun byPopularity(): SymmetricKeyAlgorithmNegotiator { return object : SymmetricKeyAlgorithmNegotiator { override fun negotiate( policy: Policy.SymmetricKeyAlgorithmPolicy, override: SymmetricKeyAlgorithm?, keyPreferences: List> ): SymmetricKeyAlgorithm { if (override == SymmetricKeyAlgorithm.NULL) { throw IllegalArgumentException( "Algorithm override cannot be NULL (plaintext).") } if (override != null) { return override } // algorithm to #occurrences val supportWeight = buildMap { keyPreferences.forEach { keyPreference -> keyPreference.forEach { pref -> put(pref, getOrDefault(pref, 0) as Int + 1) } } } // Pivot map and sort by popularity ascending // score to list(algo) val byScore = supportWeight .toList() .map { e -> e.second to e.first } .groupBy { e -> e.first } .map { e -> e.key to e.value.map { it.second }.toList() } .associate { e -> e } .toSortedMap() // iterate in reverse over algorithms for (e in byScore.entries.reversed()) { val best = policy.selectBest(e.value) if (best != null) { return best } } return policy.defaultSymmetricKeyAlgorithm } } } } }