From e3f51fbf564b786c3a7e601179f8b73cdc15c840 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Fri, 1 Sep 2023 13:43:04 +0200 Subject: [PATCH] Kotlin conversion: SecretKeyPassphraseProvider and subclasses This commit also adds a workaround to build.gradle which enables proper Java interop for Kotlin interfaces with default implementations --- build.gradle | 7 ++++ .../key/protection/package-info.java | 8 ---- .../MapBasedPassphraseProvider.java | 42 ------------------- .../SecretKeyPassphraseProvider.java | 40 ------------------ .../SolitaryPassphraseProvider.java | 33 --------------- .../passphrase_provider/package-info.java | 8 ---- .../MapBasedPassphraseProvider.kt | 21 ++++++++++ .../SecretKeyPassphraseProvider.kt | 39 +++++++++++++++++ .../SolitaryPassphraseProvider.kt | 17 ++++++++ 9 files changed, 84 insertions(+), 131 deletions(-) delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/key/protection/package-info.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/package-info.java create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.kt create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.kt create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.kt diff --git a/build.gradle b/build.gradle index 540037a8..57cc04c4 100644 --- a/build.gradle +++ b/build.gradle @@ -67,6 +67,13 @@ allprojects { fileMode = 0644 } + // Compatibility of default implementations in kotlin interfaces with Java implementations. + tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions { + freeCompilerArgs += ["-Xjvm-default=all-compatibility"] + } + } + project.ext { rootConfigDir = new File(rootDir, 'config') gitCommit = getGitCommit() diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/protection/package-info.java b/pgpainless-core/src/main/java/org/pgpainless/key/protection/package-info.java deleted file mode 100644 index b936025f..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/key/protection/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-FileCopyrightText: 2018 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -/** - * Classes related to OpenPGP secret key password protection. - */ -package org.pgpainless.key.protection; diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.java b/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.java deleted file mode 100644 index 3f0ee2f9..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: 2020 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.key.protection.passphrase_provider; - -import java.util.Map; -import javax.annotation.Nullable; - -import org.pgpainless.util.Passphrase; - -/** - * Implementation of the {@link SecretKeyPassphraseProvider} that holds a map of different {@link Passphrase passphrases}. - * It will return the right passphrase depending on the key-id. - * - * Note: This provider might return null! - * TODO: Make this null-safe and throw an exception instead? - */ -public class MapBasedPassphraseProvider implements SecretKeyPassphraseProvider { - - private final Map map; - - /** - * Create a new map based passphrase provider. - * - * @param passphraseMap map of key-ids and passphrases - */ - public MapBasedPassphraseProvider(Map passphraseMap) { - this.map = passphraseMap; - } - - @Nullable - @Override - public Passphrase getPassphraseFor(long keyId) { - return map.get(keyId); - } - - @Override - public boolean hasPassphrase(long keyId) { - return map.containsKey(keyId); - } -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.java b/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.java deleted file mode 100644 index 91c2bc95..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.java +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-FileCopyrightText: 2018 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.key.protection.passphrase_provider; - -import javax.annotation.Nullable; - -import org.bouncycastle.openpgp.PGPSecretKey; -import org.pgpainless.util.Passphrase; - -/** - * Interface to allow the user to provide a {@link Passphrase} for an encrypted OpenPGP secret key. - */ -public interface SecretKeyPassphraseProvider { - - /** - * Return a passphrase for the given secret key. - * If no record is found, return null. - * Note: In case of an unprotected secret key, this method must may not return null, but a {@link Passphrase} with - * a content of null. - * - * @param secretKey secret key - * @return passphrase or null, if no passphrase record is found. - */ - @Nullable default Passphrase getPassphraseFor(PGPSecretKey secretKey) { - return getPassphraseFor(secretKey.getKeyID()); - } - /** - * Return a passphrase for the given key. If no record has been found, return null. - * Note: In case of an unprotected secret key, this method must may not return null, but a {@link Passphrase} with - * a content of null. - * - * @param keyId if of the secret key - * @return passphrase or null, if no passphrase record has been found. - */ - @Nullable Passphrase getPassphraseFor(long keyId); - - boolean hasPassphrase(long keyId); -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.java b/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.java deleted file mode 100644 index 9400229b..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.java +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-FileCopyrightText: 2020 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.key.protection.passphrase_provider; - -import javax.annotation.Nullable; - -import org.pgpainless.util.Passphrase; - -/** - * Implementation of the {@link SecretKeyPassphraseProvider} that holds a single {@link Passphrase}. - */ -public class SolitaryPassphraseProvider implements SecretKeyPassphraseProvider { - - private final Passphrase passphrase; - - public SolitaryPassphraseProvider(Passphrase passphrase) { - this.passphrase = passphrase; - } - - @Nullable - @Override - public Passphrase getPassphraseFor(long keyId) { - // always return the same passphrase. - return passphrase; - } - - @Override - public boolean hasPassphrase(long keyId) { - return true; - } -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/package-info.java b/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/package-info.java deleted file mode 100644 index e70ad81f..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/key/protection/passphrase_provider/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-FileCopyrightText: 2020 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -/** - * Passphrase Provider classes. - */ -package org.pgpainless.key.protection.passphrase_provider; diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.kt new file mode 100644 index 00000000..22260126 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.kt @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.key.protection.passphrase_provider + +import org.pgpainless.util.Passphrase + +/** + * Implementation of the [SecretKeyPassphraseProvider] that holds a map of key-IDs and respective [Passphrase]. + * It will return the right passphrase depending on the key-id. + * + * Note: This provider might return null! + * TODO: Make this null-safe and throw an exception instead? + */ +class MapBasedPassphraseProvider(val map: Map) : SecretKeyPassphraseProvider { + + override fun getPassphraseFor(keyId: Long): Passphrase? = map[keyId] + + override fun hasPassphrase(keyId: Long): Boolean = map.containsKey(keyId) +} \ No newline at end of file diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.kt new file mode 100644 index 00000000..aaf24b70 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.kt @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.key.protection.passphrase_provider + +import org.bouncycastle.openpgp.PGPSecretKey +import org.pgpainless.util.Passphrase + +/** + * Interface to allow the user to provide a [Passphrase] for an encrypted OpenPGP secret key. + */ +interface SecretKeyPassphraseProvider { + + /** + * Return a passphrase for the given secret key. + * If no record is found, return null. + * Note: In case of an unprotected secret key, this method must may not return null, but a [Passphrase] with + * a content of null. + * + * @param secretKey secret key + * @return passphrase or null, if no passphrase record is found. + */ + fun getPassphraseFor(secretKey: PGPSecretKey): Passphrase? { + return getPassphraseFor(secretKey.keyID) + } + + /** + * Return a passphrase for the given key. If no record has been found, return null. + * Note: In case of an unprotected secret key, this method must may not return null, but a [Passphrase] with + * a content of null. + * + * @param keyId if of the secret key + * @return passphrase or null, if no passphrase record has been found. + */ + fun getPassphraseFor(keyId: Long): Passphrase? + + fun hasPassphrase(keyId: Long): Boolean +} \ No newline at end of file diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.kt new file mode 100644 index 00000000..46f77342 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.kt @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.key.protection.passphrase_provider + +import org.pgpainless.util.Passphrase + +/** + * Implementation of the [SecretKeyPassphraseProvider] that holds a single [Passphrase]. + */ +class SolitaryPassphraseProvider(val passphrase: Passphrase?) : SecretKeyPassphraseProvider { + + override fun getPassphraseFor(keyId: Long): Passphrase? = passphrase + + override fun hasPassphrase(keyId: Long): Boolean = true +} \ No newline at end of file