Skip to content

Commit

Permalink
Make providers use only ByteArray and not ByteString
Browse files Browse the repository at this point in the history
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
  • Loading branch information
whyoleg committed Sep 9, 2024
1 parent 8b7eefe commit 297f9dc
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 39 deletions.
5 changes: 4 additions & 1 deletion cryptography-core/api/cryptography-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 3 additions & 1 deletion cryptography-core/api/cryptography-core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import kotlinx.io.bytestring.*

@SubclassOptInRequired(CryptographyProviderApi::class)
public interface SharedSecretGenerator<K : Key> {
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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<ECDH.PublicKey, ECDH.PrivateKey, ECDH.KeyPair>(state), ECDH {
override fun JPublicKey.convert(): ECDH.PublicKey = EcdhPublicKey(state, this)
Expand All @@ -26,7 +25,7 @@ internal class JdkEcdh(state: JdkCryptographyState) : JdkEc<ECDH.PublicKey, ECDH
) : ECDH.PublicKey, BaseEcPublicKey(key), SharedSecretGenerator<ECDH.PrivateKey> {
private val keyAgreement = state.keyAgreement("ECDH")
override fun sharedSecretGenerator(): SharedSecretGenerator<ECDH.PrivateKey> = 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)
Expand All @@ -39,7 +38,7 @@ internal class JdkEcdh(state: JdkCryptographyState) : JdkEc<ECDH.PublicKey, ECDH
) : ECDH.PrivateKey, BaseEcPrivateKey(key), SharedSecretGenerator<ECDH.PublicKey> {
private val keyAgreement = state.keyAgreement("ECDH")
override fun sharedSecretGenerator(): SharedSecretGenerator<ECDH.PublicKey> = 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<JKeyAgreement>.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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -111,7 +109,7 @@ internal object Openssl3Ecdh : ECDH {

override fun sharedSecretGenerator(): SharedSecretGenerator<ECDH.PublicKey> = 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)
Expand All @@ -135,19 +133,19 @@ internal object Openssl3Ecdh : ECDH {

override fun sharedSecretGenerator(): SharedSecretGenerator<ECDH.PrivateKey> = 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)
}
}
}

@OptIn(UnsafeNumber::class, UnsafeByteStringApi::class)
@OptIn(UnsafeNumber::class)
private fun deriveSharedSecret(
publicKey: CPointer<EVP_PKEY>,
privateKey: CPointer<EVP_PKEY>,
): ByteString = memScoped {
): ByteArray = memScoped {
val context = checkError(EVP_PKEY_CTX_new_from_pkey(null, privateKey, null))
try {
checkError(EVP_PKEY_derive_init(context))
Expand All @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<ECDH.PublicKey, ECDH.PrivateKey, ECDH.KeyPair>(
algorithmName = "ECDH",
Expand All @@ -27,38 +25,32 @@ internal object WebCryptoEcdh : WebCryptoEc<ECDH.PublicKey, ECDH.PrivateKey, ECD
) : EcPublicKey(publicKey), ECDH.PublicKey, SharedSecretGenerator<ECDH.PrivateKey> {
override fun sharedSecretGenerator(): SharedSecretGenerator<ECDH.PrivateKey> = 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(
privateKey: CryptoKey,
) : EcPrivateKey(privateKey), ECDH.PrivateKey, SharedSecretGenerator<ECDH.PublicKey> {
override fun sharedSecretGenerator(): SharedSecretGenerator<ECDH.PublicKey> = 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()
}
}

0 comments on commit 297f9dc

Please sign in to comment.