mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-09 10:19:39 +02:00
Implement applying algorithm preferences as extension functions
This commit is contained in:
parent
deaf9fa404
commit
4dadc7c445
4 changed files with 130 additions and 109 deletions
|
@ -19,7 +19,7 @@ import org.bouncycastle.openpgp.api.OpenPGPKeyReader
|
|||
import org.bouncycastle.openpgp.api.bc.BcOpenPGPApi
|
||||
import org.pgpainless.algorithm.OpenPGPKeyVersion
|
||||
import org.pgpainless.bouncycastle.PolicyAdapter
|
||||
import org.pgpainless.bouncycastle.helpers.SignatureSubpacketsFunctionHelper
|
||||
import org.pgpainless.bouncycastle.extensions.setAlgorithmSuite
|
||||
import org.pgpainless.decryption_verification.DecryptionBuilder
|
||||
import org.pgpainless.encryption_signing.EncryptionBuilder
|
||||
import org.pgpainless.key.certification.CertifyCertificate
|
||||
|
@ -58,24 +58,7 @@ class PGPainless(
|
|||
): OpenPGPKeyGenerator =
|
||||
OpenPGPKeyGenerator(
|
||||
implementation, version.numeric, version == OpenPGPKeyVersion.v6, creationTime)
|
||||
.apply {
|
||||
val genAlgs = algorithmPolicy.keyGenerationAlgorithmSuite
|
||||
// Set default algorithm preferences from AlgorithmSuite
|
||||
setDefaultFeatures(
|
||||
SignatureSubpacketsFunctionHelper.applyFeatures(true, genAlgs.features))
|
||||
setDefaultSymmetricKeyPreferences(
|
||||
SignatureSubpacketsFunctionHelper.applySymmetricAlgorithmPreferences(
|
||||
true, genAlgs.symmetricKeyAlgorithms))
|
||||
setDefaultHashAlgorithmPreferences(
|
||||
SignatureSubpacketsFunctionHelper.applyHashAlgorithmPreferences(
|
||||
true, genAlgs.hashAlgorithms))
|
||||
setDefaultCompressionAlgorithmPreferences(
|
||||
SignatureSubpacketsFunctionHelper.applyCompressionAlgorithmPreferences(
|
||||
true, genAlgs.compressionAlgorithms))
|
||||
setDefaultAeadAlgorithmPreferences(
|
||||
SignatureSubpacketsFunctionHelper.applyAEADAlgorithmSuites(
|
||||
false, genAlgs.aeadAlgorithms))
|
||||
}
|
||||
.setAlgorithmSuite(algorithmPolicy.keyGenerationAlgorithmSuite)
|
||||
|
||||
fun readKey(): OpenPGPKeyReader = api.readKeyOrCertificate()
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.bouncycastle.extensions
|
||||
|
||||
import org.bouncycastle.bcpg.sig.PreferredAEADCiphersuites
|
||||
import org.bouncycastle.openpgp.api.OpenPGPKeyGenerator
|
||||
import org.pgpainless.algorithm.AEADCipherMode
|
||||
import org.pgpainless.algorithm.AlgorithmSuite
|
||||
import org.pgpainless.algorithm.CompressionAlgorithm
|
||||
import org.pgpainless.algorithm.Feature
|
||||
import org.pgpainless.algorithm.HashAlgorithm
|
||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm
|
||||
|
||||
/**
|
||||
* Apply different algorithm preferences (features, symmetric-key-, hash-, compression- and AEAD
|
||||
* algorithm preferences to the [OpenPGPKeyGenerator] for key generation. The preferences will be
|
||||
* set on preference-signatures on the generated keys.
|
||||
*
|
||||
* @param algorithms algorithm suite
|
||||
* @return this
|
||||
*/
|
||||
fun OpenPGPKeyGenerator.setAlgorithmSuite(algorithms: AlgorithmSuite): OpenPGPKeyGenerator {
|
||||
setDefaultFeatures(true, algorithms.features)
|
||||
setDefaultSymmetricKeyPreferences(true, algorithms.symmetricKeyAlgorithms)
|
||||
setDefaultHashAlgorithmPreferences(true, algorithms.hashAlgorithms)
|
||||
setDefaultCompressionAlgorithmPreferences(true, algorithms.compressionAlgorithms)
|
||||
setDefaultAeadAlgorithmPreferences(false, algorithms.aeadAlgorithms)
|
||||
return this
|
||||
}
|
||||
|
||||
fun OpenPGPKeyGenerator.setDefaultFeatures(
|
||||
critical: Boolean = true,
|
||||
features: Set<Feature>
|
||||
): OpenPGPKeyGenerator {
|
||||
this.setDefaultFeatures {
|
||||
val b = Feature.toBitmask(*features.toTypedArray())
|
||||
it.apply { setFeature(critical, b) }
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Define [SymmetricKeyAlgorithms][SymmetricKeyAlgorithm] that will be applied as symmetric key
|
||||
* algorithm preferences to preference-signatures on freshly generated keys.
|
||||
*
|
||||
* @param critical whether to mark the preference subpacket as critical
|
||||
* @param symmetricKeyAlgorithms ordered set of preferred symmetric key algorithms
|
||||
* @return this
|
||||
*/
|
||||
fun OpenPGPKeyGenerator.setDefaultSymmetricKeyPreferences(
|
||||
critical: Boolean = true,
|
||||
symmetricKeyAlgorithms: Set<SymmetricKeyAlgorithm>?
|
||||
): OpenPGPKeyGenerator = apply {
|
||||
symmetricKeyAlgorithms?.let { algorithms ->
|
||||
this.setDefaultSymmetricKeyPreferences {
|
||||
val algorithmIds = algorithms.map { a -> a.algorithmId }.toIntArray()
|
||||
it.apply { setPreferredSymmetricAlgorithms(critical, algorithmIds) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define [HashAlgorithms][HashAlgorithm] that will be applied as hash algorithm preferences to
|
||||
* preference-signatures on freshly generated keys.
|
||||
*
|
||||
* @param critical whether to mark the preference subpacket as critical
|
||||
* @param hashAlgorithms ordered set of preferred hash algorithms
|
||||
* @return this
|
||||
*/
|
||||
fun OpenPGPKeyGenerator.setDefaultHashAlgorithmPreferences(
|
||||
critical: Boolean = true,
|
||||
hashAlgorithms: Set<HashAlgorithm>?
|
||||
): OpenPGPKeyGenerator = apply {
|
||||
hashAlgorithms?.let { algorithms ->
|
||||
this.setDefaultHashAlgorithmPreferences {
|
||||
val algorithmIds = algorithms.map { a -> a.algorithmId }.toIntArray()
|
||||
it.apply { setPreferredHashAlgorithms(critical, algorithmIds) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define [CompressionAlgorithms][CompressionAlgorithm] that will be applied as compression
|
||||
* algorithm preferences to preference-signatures on freshly generated keys.
|
||||
*
|
||||
* @param critical whether to mark the preference subpacket as critical
|
||||
* @param compressionAlgorithms ordered set of preferred compression algorithms
|
||||
* @return this
|
||||
*/
|
||||
fun OpenPGPKeyGenerator.setDefaultCompressionAlgorithmPreferences(
|
||||
critical: Boolean = true,
|
||||
compressionAlgorithms: Set<CompressionAlgorithm>?
|
||||
): OpenPGPKeyGenerator = apply {
|
||||
compressionAlgorithms?.let { algorithms ->
|
||||
this.setDefaultCompressionAlgorithmPreferences {
|
||||
val algorithmIds = algorithms.map { a -> a.algorithmId }.toIntArray()
|
||||
it.apply { setPreferredCompressionAlgorithms(critical, algorithmIds) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define [AEADCipherModes][AEADCipherMode] that will be applied as AEAD algorithm preferences to
|
||||
* preference signatures on freshly generated keys.
|
||||
*
|
||||
* @param critical whether to mark the preferences subpacket as critical
|
||||
* @param aeadAlgorithms ordered set of AEAD preferences
|
||||
* @return this
|
||||
*/
|
||||
fun OpenPGPKeyGenerator.setDefaultAeadAlgorithmPreferences(
|
||||
critical: Boolean = false,
|
||||
aeadAlgorithms: Set<AEADCipherMode>?
|
||||
): OpenPGPKeyGenerator = apply {
|
||||
aeadAlgorithms?.let { algorithms ->
|
||||
this.setDefaultAeadAlgorithmPreferences {
|
||||
val builder = PreferredAEADCiphersuites.builder(critical)
|
||||
for (ciphermode: AEADCipherMode in algorithms) {
|
||||
builder.addCombination(
|
||||
ciphermode.ciphermode.algorithmId, ciphermode.aeadAlgorithm.algorithmId)
|
||||
}
|
||||
it.apply { setPreferredAEADCiphersuites(builder) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.bouncycastle.helpers
|
||||
|
||||
import org.bouncycastle.bcpg.sig.PreferredAEADCiphersuites
|
||||
import org.bouncycastle.openpgp.api.SignatureSubpacketsFunction
|
||||
import org.pgpainless.algorithm.AEADCipherMode
|
||||
import org.pgpainless.algorithm.CompressionAlgorithm
|
||||
import org.pgpainless.algorithm.Feature
|
||||
import org.pgpainless.algorithm.HashAlgorithm
|
||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm
|
||||
|
||||
class SignatureSubpacketsFunctionHelper {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun applySymmetricAlgorithmPreferences(
|
||||
critical: Boolean = true,
|
||||
symmetricAlgorithms: Set<SymmetricKeyAlgorithm>?
|
||||
): SignatureSubpacketsFunction {
|
||||
return symmetricAlgorithms?.let { algorithms ->
|
||||
val algorithmIds = algorithms.map { it.algorithmId }.toIntArray()
|
||||
SignatureSubpacketsFunction {
|
||||
it.apply { setPreferredSymmetricAlgorithms(critical, algorithmIds) }
|
||||
}
|
||||
}
|
||||
?: SignatureSubpacketsFunction { it }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun applyHashAlgorithmPreferences(
|
||||
critical: Boolean = true,
|
||||
hashAlgorithms: Set<HashAlgorithm>?
|
||||
): SignatureSubpacketsFunction {
|
||||
return hashAlgorithms?.let { algorithms ->
|
||||
val algorithmIds = algorithms.map { it.algorithmId }.toIntArray()
|
||||
SignatureSubpacketsFunction {
|
||||
it.apply { setPreferredHashAlgorithms(critical, algorithmIds) }
|
||||
}
|
||||
}
|
||||
?: SignatureSubpacketsFunction { it }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun applyCompressionAlgorithmPreferences(
|
||||
critical: Boolean = true,
|
||||
compressionAlgorithms: Set<CompressionAlgorithm>?
|
||||
): SignatureSubpacketsFunction {
|
||||
return compressionAlgorithms?.let { algorithms ->
|
||||
val algorithmIds = algorithms.map { it.algorithmId }.toIntArray()
|
||||
SignatureSubpacketsFunction {
|
||||
it.apply { setPreferredCompressionAlgorithms(critical, algorithmIds) }
|
||||
}
|
||||
}
|
||||
?: SignatureSubpacketsFunction { it }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun applyAEADAlgorithmSuites(
|
||||
critical: Boolean = true,
|
||||
aeadAlgorithms: Set<AEADCipherMode>?
|
||||
): SignatureSubpacketsFunction {
|
||||
return aeadAlgorithms?.let { algorithms ->
|
||||
SignatureSubpacketsFunction {
|
||||
val builder = PreferredAEADCiphersuites.builder(critical)
|
||||
for (ciphermode: AEADCipherMode in algorithms) {
|
||||
builder.addCombination(
|
||||
ciphermode.ciphermode.algorithmId, ciphermode.aeadAlgorithm.algorithmId)
|
||||
}
|
||||
it.apply { setPreferredAEADCiphersuites(builder) }
|
||||
}
|
||||
}
|
||||
?: SignatureSubpacketsFunction { it }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun applyFeatures(
|
||||
critical: Boolean = true,
|
||||
features: Set<Feature>
|
||||
): SignatureSubpacketsFunction {
|
||||
return SignatureSubpacketsFunction {
|
||||
val b = Feature.toBitmask(*features.toTypedArray())
|
||||
it.apply { setFeature(critical, b) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -96,6 +96,8 @@ public class GenerateV6KeyTest {
|
|||
OpenPGPCertificate certificate = key.toCertificate();
|
||||
assertFalse(certificate.isSecretKey());
|
||||
|
||||
// CHECKSTYLE:OFF
|
||||
System.out.println(certificate.toAsciiArmoredString());
|
||||
// CHECKSTYLE:ON
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue