Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ internal object CryptoKitCryptographyProvider : CryptographyProvider() {
AES.GCM -> CryptoKitAesGcm
ECDSA -> CryptoKitEcdsa
ECDH -> CryptoKitEcdh
EdDSA -> CryptoKitEdDSA
XDH -> CryptoKitXDH
else -> null
} as A?
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* Copyright (c) 2025 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
*/

package dev.whyoleg.cryptography.providers.cryptokit.algorithms

import dev.whyoleg.cryptography.algorithms.*
import dev.whyoleg.cryptography.materials.key.*
import dev.whyoleg.cryptography.operations.*
import dev.whyoleg.cryptography.providers.cryptokit.internal.*
import dev.whyoleg.cryptography.providers.cryptokit.internal.swiftinterop.*
import dev.whyoleg.cryptography.providers.base.*
import dev.whyoleg.cryptography.providers.base.materials.*
import dev.whyoleg.cryptography.providers.base.operations.*
import dev.whyoleg.cryptography.serialization.asn1.*
import dev.whyoleg.cryptography.serialization.asn1.modules.*
import dev.whyoleg.cryptography.serialization.pem.*
import kotlinx.cinterop.*
import platform.Foundation.*

internal object CryptoKitEdDSA : EdDSA {
override fun publicKeyDecoder(curve: EdDSA.Curve): KeyDecoder<EdDSA.PublicKey.Format, EdDSA.PublicKey> {
check(curve == EdDSA.Curve.Ed25519) { "CryptoKit supports Ed25519 only" }
return object : KeyDecoder<EdDSA.PublicKey.Format, EdDSA.PublicKey> {
override fun decodeFromByteArrayBlocking(format: EdDSA.PublicKey.Format, bytes: ByteArray): EdDSA.PublicKey = when (format) {
EdDSA.PublicKey.Format.RAW -> EdPublicKey(
swiftTry<SwiftEdDsaPublicKey> { error -> bytes.useNSData { SwiftEdDsaPublicKey.decodeRawWithRawRepresentation(it, error) } }
)
EdDSA.PublicKey.Format.DER -> {
val raw = unwrapSubjectPublicKeyInfo(ObjectIdentifier.Ed25519, bytes)
EdPublicKey(swiftTry { error -> raw.useNSData { SwiftEdDsaPublicKey.decodeRawWithRawRepresentation(it, error) } })
}
EdDSA.PublicKey.Format.PEM -> {
val der = unwrapPem(PemLabel.PublicKey, bytes)
val raw = unwrapSubjectPublicKeyInfo(ObjectIdentifier.Ed25519, der)
EdPublicKey(swiftTry { error -> raw.useNSData { SwiftEdDsaPublicKey.decodeRawWithRawRepresentation(it, error) } })
}
else -> error("$format is not supported by CryptoKit EdDSA")
}
}
}

override fun privateKeyDecoder(curve: EdDSA.Curve): KeyDecoder<EdDSA.PrivateKey.Format, EdDSA.PrivateKey> {
check(curve == EdDSA.Curve.Ed25519) { "CryptoKit supports Ed25519 only" }
return object : KeyDecoder<EdDSA.PrivateKey.Format, EdDSA.PrivateKey> {
override fun decodeFromByteArrayBlocking(format: EdDSA.PrivateKey.Format, bytes: ByteArray): EdDSA.PrivateKey = when (format) {
EdDSA.PrivateKey.Format.RAW -> EdPrivateKey(
swiftTry<SwiftEdDsaPrivateKey> { error -> bytes.useNSData { SwiftEdDsaPrivateKey.decodeRawWithRawRepresentation(it, error) } }
)
EdDSA.PrivateKey.Format.DER -> {
val raw = unwrapPrivateKeyInfo(ObjectIdentifier.Ed25519, bytes)
EdPrivateKey(swiftTry { error -> raw.useNSData { SwiftEdDsaPrivateKey.decodeRawWithRawRepresentation(it, error) } })
}
EdDSA.PrivateKey.Format.PEM -> {
val der = unwrapPem(PemLabel.PrivateKey, bytes)
val raw = unwrapPrivateKeyInfo(ObjectIdentifier.Ed25519, der)
EdPrivateKey(swiftTry { error -> raw.useNSData { SwiftEdDsaPrivateKey.decodeRawWithRawRepresentation(it, error) } })
}
else -> error("$format is not supported by CryptoKit EdDSA")
}
}
}

override fun keyPairGenerator(curve: EdDSA.Curve): KeyGenerator<EdDSA.KeyPair> {
check(curve == EdDSA.Curve.Ed25519) { "CryptoKit supports Ed25519 only" }
return object : KeyGenerator<EdDSA.KeyPair> {
override fun generateKeyBlocking(): EdDSA.KeyPair {
val p = SwiftEdDsaPrivateKey.generate()
return EdKeyPair(EdPublicKey(p.publicKey()), EdPrivateKey(p))
}
}
}

private class EdKeyPair(
override val publicKey: EdDSA.PublicKey,
override val privateKey: EdDSA.PrivateKey,
) : EdDSA.KeyPair

private class EdPublicKey(
val key: SwiftEdDsaPublicKey,
) : EdDSA.PublicKey {
override fun encodeToByteArrayBlocking(format: EdDSA.PublicKey.Format): ByteArray = when (format) {
EdDSA.PublicKey.Format.RAW -> {
val raw = key.rawRepresentation().toByteArray()
raw
}
EdDSA.PublicKey.Format.DER -> {
val raw = key.rawRepresentation().toByteArray()
wrapSubjectPublicKeyInfo(
UnknownKeyAlgorithmIdentifier(ObjectIdentifier.Ed25519),
raw
)
}
EdDSA.PublicKey.Format.PEM -> {
val raw = key.rawRepresentation().toByteArray()
wrapPem(
PemLabel.PublicKey,
wrapSubjectPublicKeyInfo(
UnknownKeyAlgorithmIdentifier(ObjectIdentifier.Ed25519),
raw
)
)
}
else -> error("$format is not supported by CryptoKit EdDSA")
}

override fun signatureVerifier(): SignatureVerifier = object : SignatureVerifier {
override fun createVerifyFunction(): VerifyFunction =
AccumulatingVerifyFunction { data, signature, startIndex, endIndex ->
val sig = signature.copyOfRange(startIndex, endIndex)
val ok = data.useNSData { dataNs -> sig.useNSData { sigNs ->
key.verifyWithSignature(sigNs, message = dataNs)
} } as Boolean
ok
}
}
}

private class EdPrivateKey(
val key: SwiftEdDsaPrivateKey,
) : EdDSA.PrivateKey {
override fun encodeToByteArrayBlocking(format: EdDSA.PrivateKey.Format): ByteArray = when (format) {
EdDSA.PrivateKey.Format.RAW -> {
val raw = key.rawRepresentation().toByteArray()
raw
}
EdDSA.PrivateKey.Format.DER -> {
val raw = key.rawRepresentation().toByteArray()
wrapPrivateKeyInfo(
0,
UnknownKeyAlgorithmIdentifier(ObjectIdentifier.Ed25519),
raw
)
}
EdDSA.PrivateKey.Format.PEM -> {
val raw = key.rawRepresentation().toByteArray()
wrapPem(
PemLabel.PrivateKey,
wrapPrivateKeyInfo(
0,
UnknownKeyAlgorithmIdentifier(ObjectIdentifier.Ed25519),
raw
)
)
}
else -> error("$format is not supported by CryptoKit EdDSA")
}

override fun signatureGenerator(): SignatureGenerator = object : SignatureGenerator {
override fun createSignFunction(): SignFunction =
AccumulatingSignFunction { data ->
swiftTry { error -> data.useNSData { key.signWithMessage(it, error) } }.toByteArray()
}
override fun generateSignatureBlocking(data: ByteArray): ByteArray =
swiftTry { error -> data.useNSData { key.signWithMessage(it, error) } }.toByteArray()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Copyright (c) 2025 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
*/

package dev.whyoleg.cryptography.providers.cryptokit.algorithms

import dev.whyoleg.cryptography.algorithms.*
import dev.whyoleg.cryptography.materials.key.*
import dev.whyoleg.cryptography.operations.*
import dev.whyoleg.cryptography.providers.cryptokit.internal.*
import dev.whyoleg.cryptography.providers.cryptokit.internal.swiftinterop.*
import dev.whyoleg.cryptography.providers.base.*
import dev.whyoleg.cryptography.providers.base.materials.*
import dev.whyoleg.cryptography.serialization.asn1.*
import dev.whyoleg.cryptography.serialization.asn1.modules.*
import dev.whyoleg.cryptography.serialization.pem.*
import kotlinx.cinterop.*
import platform.Foundation.*

internal object CryptoKitXDH : XDH {
override fun publicKeyDecoder(curve: XDH.Curve): KeyDecoder<XDH.PublicKey.Format, XDH.PublicKey> {
check(curve == XDH.Curve.X25519) { "CryptoKit supports X25519 only" }
return object : KeyDecoder<XDH.PublicKey.Format, XDH.PublicKey> {
override fun decodeFromByteArrayBlocking(format: XDH.PublicKey.Format, bytes: ByteArray): XDH.PublicKey = when (format) {
XDH.PublicKey.Format.RAW -> XPublicKey(
swiftTry<SwiftXdhPublicKey> { error -> bytes.useNSData { SwiftXdhPublicKey.decodeRawWithRawRepresentation(it, error) } }
)
XDH.PublicKey.Format.DER -> {
val raw = unwrapSubjectPublicKeyInfo(ObjectIdentifier.X25519, bytes)
XPublicKey(swiftTry { error -> raw.useNSData { SwiftXdhPublicKey.decodeRawWithRawRepresentation(it, error) } })
}
XDH.PublicKey.Format.PEM -> {
val der = unwrapPem(PemLabel.PublicKey, bytes)
val raw = unwrapSubjectPublicKeyInfo(ObjectIdentifier.X25519, der)
XPublicKey(swiftTry { error -> raw.useNSData { SwiftXdhPublicKey.decodeRawWithRawRepresentation(it, error) } })
}
else -> error("$format is not supported by CryptoKit XDH")
}
}
}

override fun privateKeyDecoder(curve: XDH.Curve): KeyDecoder<XDH.PrivateKey.Format, XDH.PrivateKey> {
check(curve == XDH.Curve.X25519) { "CryptoKit supports X25519 only" }
return object : KeyDecoder<XDH.PrivateKey.Format, XDH.PrivateKey> {
override fun decodeFromByteArrayBlocking(format: XDH.PrivateKey.Format, bytes: ByteArray): XDH.PrivateKey = when (format) {
XDH.PrivateKey.Format.RAW -> XPrivate(
swiftTry<SwiftXdhPrivateKey> { error -> bytes.useNSData { SwiftXdhPrivateKey.decodeRawWithRawRepresentation(it, error) } }
)
XDH.PrivateKey.Format.DER -> {
val raw = unwrapPrivateKeyInfo(ObjectIdentifier.X25519, bytes)
XPrivate(swiftTry { error -> raw.useNSData { SwiftXdhPrivateKey.decodeRawWithRawRepresentation(it, error) } })
}
XDH.PrivateKey.Format.PEM -> {
val der = unwrapPem(PemLabel.PrivateKey, bytes)
val raw = unwrapPrivateKeyInfo(ObjectIdentifier.X25519, der)
XPrivate(swiftTry { error -> raw.useNSData { SwiftXdhPrivateKey.decodeRawWithRawRepresentation(it, error) } })
}
else -> error("$format is not supported by CryptoKit XDH")
}
}
}

override fun keyPairGenerator(curve: XDH.Curve): KeyGenerator<XDH.KeyPair> {
check(curve == XDH.Curve.X25519) { "CryptoKit supports X25519 only" }
return object : KeyGenerator<XDH.KeyPair> {
override fun generateKeyBlocking(): XDH.KeyPair {
val p = SwiftXdhPrivateKey.generate()
return XKeyPair(XPublicKey(p.publicKey()), XPrivateKey(p))
}
}
}

private class XKeyPair(
override val publicKey: XDH.PublicKey,
override val privateKey: XDH.PrivateKey,
) : XDH.KeyPair

private class XPublicKey(
val key: SwiftXdhPublicKey,
) : XDH.PublicKey, SharedSecretGenerator<XDH.PrivateKey> {
override fun encodeToByteArrayBlocking(format: XDH.PublicKey.Format): ByteArray = when (format) {
XDH.PublicKey.Format.RAW -> {
val raw = key.rawRepresentation().toByteArray()
raw
}
XDH.PublicKey.Format.DER -> {
val raw = key.rawRepresentation().toByteArray()
wrapSubjectPublicKeyInfo(
UnknownKeyAlgorithmIdentifier(ObjectIdentifier.X25519),
raw
)
}
XDH.PublicKey.Format.PEM -> {
val raw = key.rawRepresentation().toByteArray()
wrapPem(
PemLabel.PublicKey,
wrapSubjectPublicKeyInfo(
UnknownKeyAlgorithmIdentifier(ObjectIdentifier.X25519),
raw
)
)
}
else -> error("$format is not supported by CryptoKit XDH")
}
override fun sharedSecretGenerator(): SharedSecretGenerator<XDH.PrivateKey> = this
override fun generateSharedSecretToByteArrayBlocking(other: XDH.PrivateKey): ByteArray {
require(other is XPrivateKey)
return swiftTry { error -> other.key.deriveSecretWith(key, error) }.toByteArray()
}
}

private class XPrivateKey(
val key: SwiftXdhPrivateKey,
) : XDH.PrivateKey, SharedSecretGenerator<XDH.PublicKey> {
override fun encodeToByteArrayBlocking(format: XDH.PrivateKey.Format): ByteArray = when (format) {
XDH.PrivateKey.Format.RAW -> {
val raw = key.rawRepresentation().toByteArray()
raw
}
XDH.PrivateKey.Format.DER -> {
val raw = key.rawRepresentation().toByteArray()
wrapPrivateKeyInfo(
0,
UnknownKeyAlgorithmIdentifier(ObjectIdentifier.X25519),
raw
)
}
XDH.PrivateKey.Format.PEM -> {
val raw = key.rawRepresentation().toByteArray()
wrapPem(
PemLabel.PrivateKey,
wrapPrivateKeyInfo(
0,
UnknownKeyAlgorithmIdentifier(ObjectIdentifier.X25519),
raw
)
)
}
else -> error("$format is not supported by CryptoKit XDH")
}
override fun sharedSecretGenerator(): SharedSecretGenerator<XDH.PublicKey> = this
override fun generateSharedSecretToByteArrayBlocking(other: XDH.PublicKey): ByteArray {
require(other is XPublicKey)
return swiftTry { error -> key.deriveSecretWith(other.key, error) }.toByteArray()
}
}
}
Loading