Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can I set my PublicKey in "provider.get(RSA.PSS)" ? #23

Closed
thanhhoai162963 opened this issue Mar 6, 2024 · 11 comments
Closed

Can I set my PublicKey in "provider.get(RSA.PSS)" ? #23

thanhhoai162963 opened this issue Mar 6, 2024 · 11 comments

Comments

@thanhhoai162963
Copy link

val ecdsa = provider.get(ECDSA)
val keyPairGenerator = ecdsa.keyPairGenerator(EC.Curve.P521)
val keyPair: ECDSA.KeyPair = keyPairGenerator.generateKey()

I wasn't found setPublicKey()

@whyoleg
Copy link
Owner

whyoleg commented Mar 6, 2024

Hey, Im not sure what do you mean by setPublicKey. What use case do you have? What are you trying to do?

@thanhhoai162963
Copy link
Author

thanhhoai162963 commented Mar 6, 2024

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) {

    }
}

@whyoleg
Copy link
Owner

whyoleg commented Mar 6, 2024

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?

@thanhhoai162963
Copy link
Author

thanhhoai162963 commented Mar 7, 2024

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()

@whyoleg
Copy link
Owner

whyoleg commented Mar 8, 2024

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.

@thanhhoai162963
Copy link
Author

thanhhoai162963 commented Mar 10, 2024

 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

@whyoleg
Copy link
Owner

whyoleg commented Mar 10, 2024

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 Base64
  • I've omitted some details, to keep intention clear

@thanhhoai162963
Copy link
Author

Thank 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

@whyoleg
Copy link
Owner

whyoleg commented Mar 11, 2024

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

@thanhhoai162963
Copy link
Author

thanhhoai162963 commented Mar 11, 2024

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")

@whyoleg
Copy link
Owner

whyoleg commented Mar 11, 2024

Cool! I'm closing an issue! JDK to cryptography-kotlin guide will be tracked in #24

@whyoleg whyoleg closed this as completed Mar 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants