Closed thanhhoai162963 closed 8 months ago
Hey, Im not sure what do you mean by setPublicKey
. What use case do you have? What are you trying to do?
I use asymmetric encryption which connect resful api. I get rsaPublicKey from api server (not need encryption). After I need set publickKey with rsaPublicKey and key random from local to encrypt(k) call api.
Example: fun encryptData(dataDes: String): String? { return try { val c = Cipher.getInstance(Algorithm.RSA_OAEP) c.init(Cipher.ENCRYPT_MODE, Key.rsaPublicKey()) // rsaPublicKey I get from api val encryptOut = c.doFinal(dataDes.toByteArray()) // dataDes random char() org.bouncycastle.util.encoders.Base64.toBase64String(encryptOut) // result "k" to call api asymmetric encryption } catch (e: Exception) {
}
}
As far as I understand you need to decode key from binary representation and then use it. In this case you will need something like: ECDSA:
val ecdsa = provider.get(ECDSA)
val publicKey = ecdsa.publicKeyDecoder(EC.Curve.P521).decodeFrom(EC.PublicKey.Format.RAW, keyByteArray) // or other format
// and then do anything with key verify or encrypt
Similar for RSA-OAEP:
val rsa = provider.get(RSA.OAEP)
val publicKey = rsa.publicKeyDecoder(SHA256).decodeFrom(RSA.PublicKey.Format.DER) // or other format
// and then do anything with key verify or encrypt
Does it helps?
val publicKey = rsa.publicKeyDecoder(SHA256).decodeFrom(RSA.PublicKey.Format.DER, myKey) //Follow I understand, Can I set publicKey = "myKey" here?
I mean i can init val rsa = provider.get(RSA.OAEP) with myKey, after I encrypt data combine (RSA.OAEP)contain mykey as
c.init(Cipher.ENCRYPT_MODE, myKey) // rsaPublicKey I get from api val encryptOut = c.doFinal(data) // dataDes random char()
Follow I understand, Can I set publicKey = "myKey" here?
Yeah, though, myKey
should be a ByteArray
, not a String
. DER format is the same format which is used in JDK APIs by default for RSA keys.
fun encryptData(dataRandom: String): String? {
return try {
val c = Cipher.getInstance("RSA/ECB/OAEPPadding")
c.init(Cipher.ENCRYPT_MODE, loadPublicKey())
val encryptOut = c.doFinal(dataRandom.toByteArray())
org.bouncycastle.util.encoders.Base64.toBase64String(encryptOut)
} catch (e: Exception) {
Log.d("error:", "error")
""
}
}
@Throws(GeneralSecurityException::class, IOException::class)
private fun loadPublicKey(): PublicKey? {
val rsaPublicKey = runBlocking {
LizAiDataStore.instance.getRsaPublicKey()?.publicKey
}
val data = Base64.decode(rsaPublicKey)
val spec = X509EncodedKeySpec(data)
val fact = KeyFactory.getInstance(Algorithm.RSA)
return fact.generatePublic(spec)
}
Thanks you very much recommend you @whyoleg , after 3 days thinking, learn about
from website, ,convery swift xcode - to kotlin mutiilplatform, I still can't convert this code. Looking forward to your suggestions
Looks like I really need to create a guide for JDK APIs to cryptography-kotlin conversion, as you are not the only one who is struggling with it :)
Here is a one way to do this:
fun encryptData(data: String): String? {
val key = loadPublicKey() ?: return null
val encryptOut = key.encryptor().encrypt(data.encodeToByteArray())
return Base64.encode(encryptOut)
}
private fun loadPublicKey(): RSA.OAEP.PublicKey? {
val rsaPublicKey = runBlocking { LizAiDataStore.instance.getRsaPublicKey()?.publicKey } ?: return null
val encodedKey: ByteArray = Base64.decode(rsaPublicKey)
return CryptographyProvider.Default.get(RSA.OAEP)
.publicKeyDecoder(SHA256)
.decode(RSA.PublicKey.Format.DER, encodedKey)
}
Notes:
Base64
here is using kotlin Base64Thank you @whyoleg. I generated encryptOut. But my server not decrypt . My server use dot Net rsa oeap follow: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.rsacryptoserviceprovider?view=netcore-3.1 keySize: 2048
Looks like .NET is using RSA OAEP with SHA1 - hint on SO: https://stackoverflow.com/a/67793433
So you need to try publicKeyDecoder(SHA1)
instead
Thanks you very much @whyoleg , it working. Special thanks. And Can I use triple des algorithm as android ?
mySecretKeyFactory = SecretKeyFactory.getInstance("DESede") cipher = Cipher.getInstance("DESede") key = mySecretKeyFactory?.generateSecret("DESede")
Cool! I'm closing an issue! JDK to cryptography-kotlin guide will be tracked in #24
val ecdsa = provider.get(ECDSA) val keyPairGenerator = ecdsa.keyPairGenerator(EC.Curve.P521) val keyPair: ECDSA.KeyPair = keyPairGenerator.generateKey()
I wasn't found setPublicKey()