From d020e7e12c9aa617eb1af00ebbc953323735a54c Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 31 Aug 2023 16:41:00 +0200 Subject: [PATCH] Kotlin conversion: KeyRingTemplates --- .../key/generation/KeyRingTemplates.java | 255 ------------------ .../key/generation/KeyRingTemplates.kt | 185 +++++++++++++ 2 files changed, 185 insertions(+), 255 deletions(-) delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/key/generation/KeyRingTemplates.java create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/KeyRingTemplates.kt diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeyRingTemplates.java b/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeyRingTemplates.java deleted file mode 100644 index 6966232b..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/key/generation/KeyRingTemplates.java +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.key.generation; - -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; -import org.pgpainless.PGPainless; -import org.pgpainless.algorithm.KeyFlag; -import org.pgpainless.key.generation.type.KeyType; -import org.pgpainless.key.generation.type.eddsa.EdDSACurve; -import org.pgpainless.key.generation.type.rsa.RsaLength; -import org.pgpainless.key.generation.type.xdh.XDHSpec; -import org.pgpainless.util.Passphrase; - -public final class KeyRingTemplates { - - public KeyRingTemplates() { - - } - - /** - * Generate an RSA OpenPGP key consisting of an RSA primary key used for certification, - * a dedicated RSA subkey used for signing and a third RSA subkey used for encryption. - * - * @param userId userId or null - * @param length length of the RSA keys - * @return key - * @throws InvalidAlgorithmParameterException in case of invalid key generation parameters - * @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider - * @throws PGPException in case of an OpenPGP related error - */ - public PGPSecretKeyRing rsaKeyRing(@Nullable CharSequence userId, - @Nonnull RsaLength length) - throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - return rsaKeyRing(userId, length, Passphrase.emptyPassphrase()); - } - - /** - * Generate an RSA OpenPGP key consisting of an RSA primary key used for certification, - * a dedicated RSA subkey used for signing and a third RSA subkey used for encryption. - * - * @param userId userId or null - * @param length length of the RSA keys - * @param password passphrase to encrypt the key with - * @return key - * @throws InvalidAlgorithmParameterException in case of invalid key generation parameters - * @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider - * @throws PGPException in case of an OpenPGP related error - */ - public PGPSecretKeyRing rsaKeyRing(@Nullable CharSequence userId, - @Nonnull RsaLength length, - @Nonnull String password) - throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - Passphrase passphrase = Passphrase.emptyPassphrase(); - if (!isNullOrEmpty(password)) { - passphrase = Passphrase.fromPassword(password); - } - return rsaKeyRing(userId, length, passphrase); - } - - /** - * Generate an RSA OpenPGP key consisting of an RSA primary key used for certification, - * a dedicated RSA subkey used for signing and a third RSA subkey used for encryption. - * - * @param userId userId or null - * @param length length of the RSA keys - * @param passphrase passphrase to encrypt the key with - * @return key - * @throws InvalidAlgorithmParameterException in case of invalid key generation parameters - * @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider - * @throws PGPException in case of an OpenPGP related error - */ - public PGPSecretKeyRing rsaKeyRing(@Nullable CharSequence userId, - @Nonnull RsaLength length, - @Nonnull Passphrase passphrase) - throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - KeyRingBuilder builder = PGPainless.buildKeyRing() - .setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER)) - .addSubkey(KeySpec.getBuilder(KeyType.RSA(length), KeyFlag.SIGN_DATA)) - .addSubkey(KeySpec.getBuilder(KeyType.RSA(length), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)); - - if (userId != null) { - builder.addUserId(userId.toString()); - } - - if (!passphrase.isEmpty()) { - builder.setPassphrase(passphrase); - } - - return builder.build(); - } - - /** - * Creates a simple, unencrypted RSA KeyPair of length {@code length} with user-id {@code userId}. - * The KeyPair consists of a single RSA master key which is used for signing, encryption and certification. - * - * @param userId user id. - * @param length length in bits. - * - * @return {@link PGPSecretKeyRing} containing the KeyPair. - * - * @throws InvalidAlgorithmParameterException in case of invalid key generation parameters - * @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider - * @throws PGPException in case of an OpenPGP related error - */ - public PGPSecretKeyRing simpleRsaKeyRing(@Nullable CharSequence userId, @Nonnull RsaLength length) - throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException { - return simpleRsaKeyRing(userId, length, Passphrase.emptyPassphrase()); - } - - public PGPSecretKeyRing simpleRsaKeyRing(@Nullable CharSequence userId, @Nonnull RsaLength length, @Nonnull Passphrase passphrase) - throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - KeyRingBuilder builder = PGPainless.buildKeyRing() - .setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS)) - .setPassphrase(passphrase); - if (userId != null) { - builder.addUserId(userId.toString()); - } - return builder.build(); - } - - /** - * Creates a simple RSA KeyPair of length {@code length} with user-id {@code userId}. - * The KeyPair consists of a single RSA master key which is used for signing, encryption and certification. - * - * @param userId user id. - * @param length length in bits. - * @param password Password of the key. Can be null for unencrypted keys. - * - * @return {@link PGPSecretKeyRing} containing the KeyPair. - * - * @throws InvalidAlgorithmParameterException in case of invalid key generation parameters - * @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider - * @throws PGPException in case of an OpenPGP related error - */ - public PGPSecretKeyRing simpleRsaKeyRing(@Nullable CharSequence userId, @Nonnull RsaLength length, @Nullable String password) - throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { - Passphrase passphrase = Passphrase.emptyPassphrase(); - if (!isNullOrEmpty(password)) { - passphrase = Passphrase.fromPassword(password); - } - return simpleRsaKeyRing(userId, length, passphrase); - } - - /** - * Creates a key ring consisting of an ed25519 EdDSA primary key and a curve25519 XDH subkey. - * The EdDSA primary key is used for signing messages and certifying the sub key. - * The XDH subkey is used for encryption and decryption of messages. - * - * @param userId user-id - * - * @return {@link PGPSecretKeyRing} containing the key pairs. - * - * @throws InvalidAlgorithmParameterException in case of invalid key generation parameters - * @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider - * @throws PGPException in case of an OpenPGP related error - */ - public PGPSecretKeyRing simpleEcKeyRing(@Nullable CharSequence userId) - throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException { - return simpleEcKeyRing(userId, Passphrase.emptyPassphrase()); - } - - /** - * Creates a key ring consisting of an ed25519 EdDSA primary key and a X25519 XDH subkey. - * The EdDSA primary key is used for signing messages and certifying the sub key. - * The XDH subkey is used for encryption and decryption of messages. - * - * @param userId user-id - * @param password Password of the private key. Can be null for an unencrypted key. - * - * @return {@link PGPSecretKeyRing} containing the key pairs. - * - * @throws InvalidAlgorithmParameterException in case of invalid key generation parameters - * @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider - * @throws PGPException in case of an OpenPGP related error - */ - public PGPSecretKeyRing simpleEcKeyRing(@Nullable CharSequence userId, String password) - throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { - Passphrase passphrase = Passphrase.emptyPassphrase(); - if (!isNullOrEmpty(password)) { - passphrase = Passphrase.fromPassword(password); - } - return simpleEcKeyRing(userId, passphrase); - } - - public PGPSecretKeyRing simpleEcKeyRing(@Nullable CharSequence userId, @Nonnull Passphrase passphrase) - throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - KeyRingBuilder builder = PGPainless.buildKeyRing() - .setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)) - .addSubkey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)) - .setPassphrase(passphrase); - if (userId != null) { - builder.addUserId(userId.toString()); - } - return builder.build(); - } - - /** - * Generate a modern PGP key ring consisting of an ed25519 EdDSA primary key which is used to certify - * an X25519 XDH encryption subkey and an ed25519 EdDSA signing key. - * - * @param userId primary user id - * @return key ring - * - * @throws InvalidAlgorithmParameterException in case of invalid key generation parameters - * @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider - * @throws PGPException in case of an OpenPGP related error - */ - public PGPSecretKeyRing modernKeyRing(@Nullable CharSequence userId) throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - return modernKeyRing(userId, Passphrase.emptyPassphrase()); - } - - /** - * Generate a modern PGP key ring consisting of an ed25519 EdDSA primary key which is used to certify - * an X25519 XDH encryption subkey and an ed25519 EdDSA signing key. - * - * @param userId primary user id - * @param password passphrase or null if the key should be unprotected. - * @return key ring - * - * @throws InvalidAlgorithmParameterException in case of invalid key generation parameters - * @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider - * @throws PGPException in case of an OpenPGP related error - */ - public PGPSecretKeyRing modernKeyRing(@Nullable CharSequence userId, @Nullable String password) - throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException { - Passphrase passphrase = (password != null ? Passphrase.fromPassword(password) : Passphrase.emptyPassphrase()); - return modernKeyRing(userId, passphrase); - } - - public PGPSecretKeyRing modernKeyRing(@Nullable CharSequence userId, @Nonnull Passphrase passphrase) - throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - KeyRingBuilder builder = PGPainless.buildKeyRing() - .setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER)) - .addSubkey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)) - .addSubkey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.SIGN_DATA)) - .setPassphrase(passphrase); - if (userId != null) { - builder.addUserId(userId.toString()); - } - return builder.build(); - } - - private static boolean isNullOrEmpty(String password) { - return password == null || password.trim().isEmpty(); - } - -} diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/KeyRingTemplates.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/KeyRingTemplates.kt new file mode 100644 index 00000000..82215971 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/KeyRingTemplates.kt @@ -0,0 +1,185 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.key.generation + +import org.bouncycastle.openpgp.PGPSecretKeyRing +import org.pgpainless.PGPainless.Companion.buildKeyRing +import org.pgpainless.algorithm.KeyFlag +import org.pgpainless.key.generation.KeySpec.Companion.getBuilder +import org.pgpainless.key.generation.type.KeyType +import org.pgpainless.key.generation.type.eddsa.EdDSACurve +import org.pgpainless.key.generation.type.rsa.RsaLength +import org.pgpainless.key.generation.type.xdh.XDHSpec +import org.pgpainless.util.Passphrase + +class KeyRingTemplates { + + /** + * Generate an RSA OpenPGP key consisting of an RSA primary key used for certification, + * a dedicated RSA subkey used for signing and a third RSA subkey used for encryption. + * + * @param userId userId or null + * @param length length of the RSA keys + * @param passphrase passphrase to encrypt the key with. Can be empty for an unencrytped key. + * @return key + */ + @JvmOverloads + fun rsaKeyRing(userId: CharSequence?, + length: RsaLength, + passphrase: Passphrase = Passphrase.emptyPassphrase() + ): PGPSecretKeyRing = buildKeyRing().apply { + setPrimaryKey(getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER)) + addSubkey(getBuilder(KeyType.RSA(length), KeyFlag.SIGN_DATA)) + addSubkey(getBuilder(KeyType.RSA(length), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)) + setPassphrase(passphrase) + if (userId != null) { + addUserId(userId) + } + }.build() + + /** + * Generate an RSA OpenPGP key consisting of an RSA primary key used for certification, + * a dedicated RSA subkey used for signing and a third RSA subkey used for encryption. + * + * @param userId userId or null + * @param length length of the RSA keys + * @param password passphrase to encrypt the key with. Can be null or blank for unencrypted keys. + * @return key + */ + fun rsaKeyRing(userId: CharSequence?, + length: RsaLength, + password: String? + ): PGPSecretKeyRing = password.let { + if (it.isNullOrBlank()) { + rsaKeyRing(userId, length, Passphrase.emptyPassphrase()) + } else { + rsaKeyRing(userId, length, Passphrase.fromPassword(it)) + } + } + + /** + * Creates a simple RSA KeyPair of length {@code length} with user-id {@code userId}. + * The KeyPair consists of a single RSA master key which is used for signing, encryption and certification. + * + * @param userId user id. + * @param length length in bits. + * @param password Password of the key. Can be empty for unencrypted keys. + * + * @return {@link PGPSecretKeyRing} containing the KeyPair. + */ + @JvmOverloads + fun simpleRsaKeyRing(userId: CharSequence?, + length: RsaLength, + passphrase: Passphrase = Passphrase.emptyPassphrase() + ): PGPSecretKeyRing = buildKeyRing().apply { + setPrimaryKey(getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS)) + setPassphrase(passphrase) + if (userId != null) { + addUserId(userId.toString()) + } + }.build() + + /** + * Creates a simple RSA KeyPair of length {@code length} with user-id {@code userId}. + * The KeyPair consists of a single RSA master key which is used for signing, encryption and certification. + * + * @param userId user id. + * @param length length in bits. + * @param password Password of the key. Can be null or blank for unencrypted keys. + * + * @return {@link PGPSecretKeyRing} containing the KeyPair. + */ + fun simpleRsaKeyRing(userId: CharSequence?, + length: RsaLength, + password: String? + ) = password.let { + if (it.isNullOrBlank()) { + simpleRsaKeyRing(userId, length, Passphrase.emptyPassphrase()) + } else { + simpleRsaKeyRing(userId, length, Passphrase.fromPassword(it)) + } + } + + /** + * Creates a key ring consisting of an ed25519 EdDSA primary key and a X25519 XDH subkey. + * The EdDSA primary key is used for signing messages and certifying the sub key. + * The XDH subkey is used for encryption and decryption of messages. + * + * @param userId user-id + * @param passphrase Password of the private key. Can be empty for an unencrypted key. + * + * @return {@link PGPSecretKeyRing} containing the key pairs. + */ + @JvmOverloads + fun simpleEcKeyRing(userId: CharSequence?, + passphrase: Passphrase = Passphrase.emptyPassphrase() + ): PGPSecretKeyRing = buildKeyRing().apply { + setPrimaryKey(getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)) + addSubkey(getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)) + setPassphrase(passphrase) + if (userId != null) { + addUserId(userId.toString()) + } + }.build() + + /** + * Creates a key ring consisting of an ed25519 EdDSA primary key and a X25519 XDH subkey. + * The EdDSA primary key is used for signing messages and certifying the sub key. + * The XDH subkey is used for encryption and decryption of messages. + * + * @param userId user-id + * @param passphrase Password of the private key. Can be null or blank for an unencrypted key. + * + * @return {@link PGPSecretKeyRing} containing the key pairs. + */ + fun simpleEcKeyRing(userId: CharSequence?, + password: String? + ): PGPSecretKeyRing = password.let { + if (it.isNullOrBlank()) { + simpleEcKeyRing(userId, Passphrase.emptyPassphrase()) + } else { + simpleEcKeyRing(userId, Passphrase.fromPassword(it)) + } + } + + /** + * Generate a modern PGP key ring consisting of an ed25519 EdDSA primary key which is used to certify + * an X25519 XDH encryption subkey and an ed25519 EdDSA signing key. + * + * @param userId primary user id + * @param passphrase passphrase for the private key. Can be empty for an unencrypted key. + * @return key ring + */ + @JvmOverloads + fun modernKeyRing(userId: CharSequence?, + passphrase: Passphrase = Passphrase.emptyPassphrase() + ): PGPSecretKeyRing = buildKeyRing().apply { + setPrimaryKey(getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER)) + addSubkey(getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)) + addSubkey(getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.SIGN_DATA)) + setPassphrase(passphrase) + if (userId != null) { + addUserId(userId) + } + }.build() + + /** + * Generate a modern PGP key ring consisting of an ed25519 EdDSA primary key which is used to certify + * an X25519 XDH encryption subkey and an ed25519 EdDSA signing key. + * + * @param userId primary user id + * @param password passphrase for the private key. Can be null or blank for an unencrypted key. + * @return key ring + */ + fun modernKeyRing(userId: CharSequence?, + password: String? + ): PGPSecretKeyRing = password.let { + if (it.isNullOrBlank()) { + modernKeyRing(userId, Passphrase.emptyPassphrase()) + } else { + modernKeyRing(userId, Passphrase.fromPassword(it)) + } + } +} \ No newline at end of file