fix(CryptographyProvider): `No providers registered. Please provide a dependency or register provider explicitly`
jvondermarck opened this issue · 2 comments
In my Kotlin Compose Multiplatform app I declare the Provider this way to be able to encrypt and decrypt text with AES.CBC in my class :
object Cryptography {
private val cryptography = CryptographyProvider.Default.get(AES.CBC)
private val secureRandom = CryptographyRandom.Default
@OptIn(DelicateCryptographyApi::class)
suspend fun encryptAesCbcPkcs5Padding(plainText: ByteArray, key: ByteArray, iv: ByteArray): ByteArray {
if (key.size != 32) {
throw IllegalArgumentException("Key size has to be 32 bytes, but is ${key.size}")
}
if (iv.size != 16) {
throw IllegalArgumentException("IV size has to be 16 bytes, but is ${iv.size}")
}
//val aes = cryptography.get(AES.CBC)
val aesKey = cryptography.keyDecoder().decodeFrom(AES.Key.Format.RAW, key)
val cipher = aesKey.cipher(padding = true) // // PKCS5Padding is implied here
return cipher.encryptBlocking(iv, plainText)
}
...
}And when I run my program I have this error :
Caused by: java.lang.IllegalStateException: No providers registered. Please provide a dependency or register provider explicitly
at dev.whyoleg.cryptography.CryptographyProvider$Companion$Default$2.invoke(CryptographyProvider.kt:33)
at dev.whyoleg.cryptography.CryptographyProvider$Companion$Default$2.invoke(CryptographyProvider.kt:31)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at dev.whyoleg.cryptography.CryptographyProvider$Companion.getDefault(CryptographyProvider.kt:31)
at de.siedle.poc.kmp.core.encryption.Cryptography.<clinit>(Cryptography.kt:12)
... 13 more
And when I try to use the method registerProvider I have an error because the Registry object contains an error annotation : "API of everything what is implemented in providers is experimental for now and subject to change (if possible in backward-compatible way)"
Find below your current code:
package dev.whyoleg.cryptography
@RequiresOptIn(
message = "API of everything what is implemented in providers is experimental for now and subject to change (if possible in backward-compatible way)",
level = RequiresOptIn.Level.ERROR
)
public annotation class CryptographyProviderApi
@SubclassOptInRequired(CryptographyProviderApi::class)
public abstract class CryptographyProvider {
public abstract val name: String
public abstract fun <A : CryptographyAlgorithm> getOrNull(identifier: CryptographyAlgorithmId<A>): A?
public open fun <A : CryptographyAlgorithm> get(identifier: CryptographyAlgorithmId<A>): A =
getOrNull(identifier) ?: throw CryptographyAlgorithmNotFoundException(identifier)
@CryptographyProviderApi
public object Registry {
private val providers = initProviders().toMutableList()
public val registeredProviders: Sequence<CryptographyProvider>
get() = providers.toList().asSequence().map(Lazy<CryptographyProvider>::value)
public fun registerProvider(provider: CryptographyProvider) {
providers.add(lazyOf(provider))
}
public fun registerProvider(provider: Lazy<CryptographyProvider>) {
providers.add(provider)
}
}
public companion object {
public val Default: CryptographyProvider by lazy {
@OptIn(CryptographyProviderApi::class)
checkNotNull(Registry.registeredProviders.firstOrNull()) {
"No providers registered. Please provide a dependency or register provider explicitly"
}
}
}
}
// used only on JVM for ServiceLoader
internal expect fun initProviders(): List<Lazy<CryptographyProvider>>My Kotlin version is 2.0.10. And I use
dev.whyoleg.cryptography:cryptography-core:0.3.1declared in thecommonMain.dependencies
Hey!
Could you please check if you have added provider dependencies.
F.e for iOS + Android case it will be something like this:
kotlin {
sourceSets {
commonMain.dependencies {
implementation(project.dependencies.platform("dev.whyoleg.cryptography:cryptography-bom:0.3.1"))
implementation("dev.whyoleg.cryptography:cryptography-core")
}
androidMain.dependencies {
implementation("dev.whyoleg.cryptography:cryptography-provider-jdk")
}
iosMain.dependencies {
implementation("dev.whyoleg.cryptography:cryptography-provider-openssl3-prebuilt")
// or `apple` provider
// implementation("dev.whyoleg.cryptography:cryptography-provider-apple")
}
}
}Wow thank you SO SO much @whyoleg !! It works perfectly now !
So I just added these two libraries iOS and Android in my build.gradle.kts and it immediately worked, there is no need for people who might ask, to use expect / actual in both platforms to set up the CryptographyProvider :)
Thank you for your quick answer ! Have a good day.