From 297f9dc094be8c80a7ea5e72b10f5debb3d7de2d Mon Sep 17 00:00:00 2001 From: Oleg Yukhnevich Date: Mon, 9 Sep 2024 22:29:51 +0300 Subject: [PATCH] Make providers use only `ByteArray` and not `ByteString` For now `ByteString` is used mostly as a wrapper. When kotlinx-io will be stable or `ByteString` will migrate to kotlin-stdlib `ByteArray` overloads will be deprecated --- cryptography-core/api/cryptography-core.api | 5 ++- .../api/cryptography-core.klib.api | 4 ++- .../operations/SharedSecretGenerator.kt | 7 ++-- .../src/jvmMain/kotlin/algorithms/JdkEcdh.kt | 5 ++- .../kotlin/operations/JdkKeyAgreement.kt | 7 ++-- .../kotlin/algorithms/Openssl3Ecdh.kt | 12 +++---- .../kotlin/algorithms/WebCryptoEcdh.kt | 32 +++++++------------ 7 files changed, 33 insertions(+), 39 deletions(-) diff --git a/cryptography-core/api/cryptography-core.api b/cryptography-core/api/cryptography-core.api index 5b9e6cdf..516568cf 100644 --- a/cryptography-core/api/cryptography-core.api +++ b/cryptography-core/api/cryptography-core.api @@ -731,7 +731,10 @@ public abstract interface class dev/whyoleg/cryptography/operations/SecretDeriva public abstract interface class dev/whyoleg/cryptography/operations/SharedSecretGenerator { public fun generateSharedSecret (Ldev/whyoleg/cryptography/materials/key/Key;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun generateSharedSecret$suspendImpl (Ldev/whyoleg/cryptography/operations/SharedSecretGenerator;Ldev/whyoleg/cryptography/materials/key/Key;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun generateSharedSecretBlocking (Ldev/whyoleg/cryptography/materials/key/Key;)Lkotlinx/io/bytestring/ByteString; + public fun generateSharedSecretBlocking (Ldev/whyoleg/cryptography/materials/key/Key;)Lkotlinx/io/bytestring/ByteString; + public fun generateSharedSecretByteArray (Ldev/whyoleg/cryptography/materials/key/Key;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun generateSharedSecretByteArray$suspendImpl (Ldev/whyoleg/cryptography/operations/SharedSecretGenerator;Ldev/whyoleg/cryptography/materials/key/Key;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun generateSharedSecretByteArrayBlocking (Ldev/whyoleg/cryptography/materials/key/Key;)[B } public abstract interface class dev/whyoleg/cryptography/operations/SignatureGenerator { diff --git a/cryptography-core/api/cryptography-core.klib.api b/cryptography-core/api/cryptography-core.klib.api index 857f6dfe..0fef0f56 100644 --- a/cryptography-core/api/cryptography-core.klib.api +++ b/cryptography-core/api/cryptography-core.klib.api @@ -404,8 +404,10 @@ abstract interface <#A: dev.whyoleg.cryptography.materials.key/Key> dev.whyoleg. } abstract interface <#A: dev.whyoleg.cryptography.materials.key/Key> dev.whyoleg.cryptography.operations/SharedSecretGenerator { // dev.whyoleg.cryptography.operations/SharedSecretGenerator|null[0] - abstract fun generateSharedSecretBlocking(#A): kotlinx.io.bytestring/ByteString // dev.whyoleg.cryptography.operations/SharedSecretGenerator.generateSharedSecretBlocking|generateSharedSecretBlocking(1:0){}[0] + abstract fun generateSharedSecretByteArrayBlocking(#A): kotlin/ByteArray // dev.whyoleg.cryptography.operations/SharedSecretGenerator.generateSharedSecretByteArrayBlocking|generateSharedSecretByteArrayBlocking(1:0){}[0] + open fun generateSharedSecretBlocking(#A): kotlinx.io.bytestring/ByteString // dev.whyoleg.cryptography.operations/SharedSecretGenerator.generateSharedSecretBlocking|generateSharedSecretBlocking(1:0){}[0] open suspend fun generateSharedSecret(#A): kotlinx.io.bytestring/ByteString // dev.whyoleg.cryptography.operations/SharedSecretGenerator.generateSharedSecret|generateSharedSecret(1:0){}[0] + open suspend fun generateSharedSecretByteArray(#A): kotlin/ByteArray // dev.whyoleg.cryptography.operations/SharedSecretGenerator.generateSharedSecretByteArray|generateSharedSecretByteArray(1:0){}[0] } abstract interface <#A: dev.whyoleg.cryptography.materials.key/KeyFormat, #B: dev.whyoleg.cryptography.materials.key/Key> dev.whyoleg.cryptography.materials.key/KeyDecoder { // dev.whyoleg.cryptography.materials.key/KeyDecoder|null[0] diff --git a/cryptography-core/src/commonMain/kotlin/operations/SharedSecretGenerator.kt b/cryptography-core/src/commonMain/kotlin/operations/SharedSecretGenerator.kt index 77fb1ceb..329244ca 100644 --- a/cryptography-core/src/commonMain/kotlin/operations/SharedSecretGenerator.kt +++ b/cryptography-core/src/commonMain/kotlin/operations/SharedSecretGenerator.kt @@ -10,6 +10,9 @@ import kotlinx.io.bytestring.* @SubclassOptInRequired(CryptographyProviderApi::class) public interface SharedSecretGenerator { - public suspend fun generateSharedSecret(other: K): ByteString = generateSharedSecretBlocking(other) - public fun generateSharedSecretBlocking(other: K): ByteString + public suspend fun generateSharedSecretByteArray(other: K): ByteArray = generateSharedSecretByteArrayBlocking(other) + public fun generateSharedSecretByteArrayBlocking(other: K): ByteArray + + public suspend fun generateSharedSecret(other: K): ByteString = generateSharedSecretByteArray(other).asByteString() + public fun generateSharedSecretBlocking(other: K): ByteString = generateSharedSecretByteArrayBlocking(other).asByteString() } diff --git a/cryptography-providers/jdk/src/jvmMain/kotlin/algorithms/JdkEcdh.kt b/cryptography-providers/jdk/src/jvmMain/kotlin/algorithms/JdkEcdh.kt index 574affed..c8739737 100644 --- a/cryptography-providers/jdk/src/jvmMain/kotlin/algorithms/JdkEcdh.kt +++ b/cryptography-providers/jdk/src/jvmMain/kotlin/algorithms/JdkEcdh.kt @@ -8,7 +8,6 @@ import dev.whyoleg.cryptography.algorithms.* import dev.whyoleg.cryptography.operations.* import dev.whyoleg.cryptography.providers.jdk.* import dev.whyoleg.cryptography.providers.jdk.operations.* -import kotlinx.io.bytestring.* internal class JdkEcdh(state: JdkCryptographyState) : JdkEc(state), ECDH { override fun JPublicKey.convert(): ECDH.PublicKey = EcdhPublicKey(state, this) @@ -26,7 +25,7 @@ internal class JdkEcdh(state: JdkCryptographyState) : JdkEc { private val keyAgreement = state.keyAgreement("ECDH") override fun sharedSecretGenerator(): SharedSecretGenerator = this - override fun generateSharedSecretBlocking(other: ECDH.PrivateKey): ByteString { + override fun generateSharedSecretByteArrayBlocking(other: ECDH.PrivateKey): ByteArray { check(other is EcdhPrivateKey) { "Only key produced by JDK provider is supported" } return keyAgreement.doAgreement(state, other.key, key) @@ -39,7 +38,7 @@ internal class JdkEcdh(state: JdkCryptographyState) : JdkEc { private val keyAgreement = state.keyAgreement("ECDH") override fun sharedSecretGenerator(): SharedSecretGenerator = this - override fun generateSharedSecretBlocking(other: ECDH.PublicKey): ByteString { + override fun generateSharedSecretByteArrayBlocking(other: ECDH.PublicKey): ByteArray { check(other is EcdhPublicKey) { "Only key produced by JDK provider is supported" } return keyAgreement.doAgreement(state, key, other.key) diff --git a/cryptography-providers/jdk/src/jvmMain/kotlin/operations/JdkKeyAgreement.kt b/cryptography-providers/jdk/src/jvmMain/kotlin/operations/JdkKeyAgreement.kt index ab776bde..882467cc 100644 --- a/cryptography-providers/jdk/src/jvmMain/kotlin/operations/JdkKeyAgreement.kt +++ b/cryptography-providers/jdk/src/jvmMain/kotlin/operations/JdkKeyAgreement.kt @@ -5,16 +5,13 @@ package dev.whyoleg.cryptography.providers.jdk.operations import dev.whyoleg.cryptography.providers.jdk.* -import kotlinx.io.bytestring.* -import kotlinx.io.bytestring.unsafe.* -@OptIn(UnsafeByteStringApi::class) internal fun Pooled.doAgreement( state: JdkCryptographyState, privateKey: JPrivateKey, publicKey: JPublicKey, -): ByteString = use { +): ByteArray = use { it.init(privateKey, state.secureRandom) it.doPhase(publicKey, true) - UnsafeByteStringOperations.wrapUnsafe(it.generateSecret()) + it.generateSecret() } diff --git a/cryptography-providers/openssl3/api/src/commonMain/kotlin/algorithms/Openssl3Ecdh.kt b/cryptography-providers/openssl3/api/src/commonMain/kotlin/algorithms/Openssl3Ecdh.kt index f39f72e6..a878e756 100644 --- a/cryptography-providers/openssl3/api/src/commonMain/kotlin/algorithms/Openssl3Ecdh.kt +++ b/cryptography-providers/openssl3/api/src/commonMain/kotlin/algorithms/Openssl3Ecdh.kt @@ -11,8 +11,6 @@ import dev.whyoleg.cryptography.providers.openssl3.internal.* import dev.whyoleg.cryptography.providers.openssl3.internal.cinterop.* import dev.whyoleg.cryptography.providers.openssl3.materials.* import kotlinx.cinterop.* -import kotlinx.io.bytestring.* -import kotlinx.io.bytestring.unsafe.* import platform.posix.* internal object Openssl3Ecdh : ECDH { @@ -111,7 +109,7 @@ internal object Openssl3Ecdh : ECDH { override fun sharedSecretGenerator(): SharedSecretGenerator = this - override fun generateSharedSecretBlocking(other: ECDH.PublicKey): ByteString { + override fun generateSharedSecretByteArrayBlocking(other: ECDH.PublicKey): ByteArray { check(other is EcPublicKey) return deriveSharedSecret(publicKey = other.key, privateKey = key) @@ -135,7 +133,7 @@ internal object Openssl3Ecdh : ECDH { override fun sharedSecretGenerator(): SharedSecretGenerator = this - override fun generateSharedSecretBlocking(other: ECDH.PrivateKey): ByteString { + override fun generateSharedSecretByteArrayBlocking(other: ECDH.PrivateKey): ByteArray { check(other is EcPrivateKey) return deriveSharedSecret(publicKey = key, privateKey = other.key) @@ -143,11 +141,11 @@ internal object Openssl3Ecdh : ECDH { } } -@OptIn(UnsafeNumber::class, UnsafeByteStringApi::class) +@OptIn(UnsafeNumber::class) private fun deriveSharedSecret( publicKey: CPointer, privateKey: CPointer, -): ByteString = memScoped { +): ByteArray = memScoped { val context = checkError(EVP_PKEY_CTX_new_from_pkey(null, privateKey, null)) try { checkError(EVP_PKEY_derive_init(context)) @@ -156,7 +154,7 @@ private fun deriveSharedSecret( checkError(EVP_PKEY_derive(context, null, secretSize.ptr)) val secret = ByteArray(secretSize.value.toInt()) checkError(EVP_PKEY_derive(context, secret.refToU(0), secretSize.ptr)) - UnsafeByteStringOperations.wrapUnsafe(secret) + secret } finally { EVP_PKEY_CTX_free(context) } diff --git a/cryptography-providers/webcrypto/src/commonMain/kotlin/algorithms/WebCryptoEcdh.kt b/cryptography-providers/webcrypto/src/commonMain/kotlin/algorithms/WebCryptoEcdh.kt index 8719ec59..e493b56e 100644 --- a/cryptography-providers/webcrypto/src/commonMain/kotlin/algorithms/WebCryptoEcdh.kt +++ b/cryptography-providers/webcrypto/src/commonMain/kotlin/algorithms/WebCryptoEcdh.kt @@ -8,8 +8,6 @@ import dev.whyoleg.cryptography.algorithms.* import dev.whyoleg.cryptography.operations.* import dev.whyoleg.cryptography.providers.webcrypto.internal.* import dev.whyoleg.cryptography.providers.webcrypto.materials.* -import kotlinx.io.bytestring.* -import kotlinx.io.bytestring.unsafe.* internal object WebCryptoEcdh : WebCryptoEc( algorithmName = "ECDH", @@ -27,19 +25,16 @@ internal object WebCryptoEcdh : WebCryptoEc { override fun sharedSecretGenerator(): SharedSecretGenerator = this - @OptIn(UnsafeByteStringApi::class) - override suspend fun generateSharedSecret(other: ECDH.PrivateKey): ByteString { + override suspend fun generateSharedSecretByteArray(other: ECDH.PrivateKey): ByteArray { check(other is EcdhPrivateKey) - return UnsafeByteStringOperations.wrapUnsafe( - WebCrypto.deriveBits( - algorithm = EcdhKeyDeriveAlgorithm(publicKey), - baseKey = other.privateKey, - length = curveOrderSize(publicKey.algorithm.ecKeyAlgorithmNamedCurve).inBits - ) + return WebCrypto.deriveBits( + algorithm = EcdhKeyDeriveAlgorithm(publicKey), + baseKey = other.privateKey, + length = curveOrderSize(publicKey.algorithm.ecKeyAlgorithmNamedCurve).inBits ) } - override fun generateSharedSecretBlocking(other: ECDH.PrivateKey): ByteString = nonBlocking() + override fun generateSharedSecretByteArrayBlocking(other: ECDH.PrivateKey): ByteArray = nonBlocking() } private class EcdhPrivateKey( @@ -47,18 +42,15 @@ internal object WebCryptoEcdh : WebCryptoEc { override fun sharedSecretGenerator(): SharedSecretGenerator = this - @OptIn(UnsafeByteStringApi::class) - override suspend fun generateSharedSecret(other: ECDH.PublicKey): ByteString { + override suspend fun generateSharedSecretByteArray(other: ECDH.PublicKey): ByteArray { check(other is EcdhPublicKey) - return UnsafeByteStringOperations.wrapUnsafe( - WebCrypto.deriveBits( - algorithm = EcdhKeyDeriveAlgorithm(other.publicKey), - baseKey = privateKey, - length = curveOrderSize(privateKey.algorithm.ecKeyAlgorithmNamedCurve).inBits - ) + return WebCrypto.deriveBits( + algorithm = EcdhKeyDeriveAlgorithm(other.publicKey), + baseKey = privateKey, + length = curveOrderSize(privateKey.algorithm.ecKeyAlgorithmNamedCurve).inBits ) } - override fun generateSharedSecretBlocking(other: ECDH.PublicKey): ByteString = nonBlocking() + override fun generateSharedSecretByteArrayBlocking(other: ECDH.PublicKey): ByteArray = nonBlocking() } }