Kotlin ECC Şifreleme
Kotlin'de Eliptik Eğri Şifreleme hakkında herhangi bir bilgi var mı?
Anahtar çiftleri oluşturmak ve şifrelemek, mesajların şifresini çözmek için.
Bu konu hakkında bilgi olmayan çok az şey var.
Örneğin ECC P-521 eliptik eğriyi uygulamak istiyorum.
Java sürümünü Kotlin içerisinde kullanmak mümkün müdür?
Ve bunu nasıl uygulayacağız?
Yanıtlar
ECC, ECC tabanlı asimetrik şifrelemeyi simetrik şifrelemeyle birleştiren karma bir şifreleme şeması olan ECIES'yi sunar. Burada, verilerin simetrik şifrelemesi için bir anahtarın türetildiği paylaşılan bir sır üretilir. Kimlik doğrulama için bir MAC kullanılır. ECIES, çeşitli kripto standartlarında belirtilmiştir. Daha fazla ayrıntı burada bulunabilir .
ECIES, sorunuzda listelediğiniz bileşenleri kullanır (ECC aracılığıyla paylaşılan sır, simetrik şifreleme, kimlik doğrulama için MAC). Bununla birlikte, belirli algoritmalar kullanılan standarda veya uygulamaya bağlıdır, bu nedenle bunlar üzerinde doğrudan kontrolünüz yoktur. Bu sizin için yeterliyse, ECIES iyi bir seçenek olacaktır.
ECIES, örneğin IEEE P 1363a standardını uygulayan BouncyCastle tarafından desteklenmektedir. ECIES'yi kullanmak için, bu nedenle önce BouncyCastle eklenmelidir (örneğin, uygulama / gradle'ın bağımlılıklar bölümündeki Android Studio için), ayrıca buraya bakın :
implementation 'org.bouncycastle:bcprov-jdk15to18:1.67'
Aşağıdaki Kotlin kodu daha sonra ECIES ve NIST P-521 ile bir şifreleme / şifre çözme gerçekleştirir:
// Add BouncyCastle
Security.removeProvider("BC")
Security.addProvider(BouncyCastleProvider())
// Key Pair Generation
val keyPairGenerator = KeyPairGenerator.getInstance("ECDH")
keyPairGenerator.initialize(ECGenParameterSpec("secp521r1"))
val keyPair = keyPairGenerator.generateKeyPair()
// Encryption
val plaintext = "The quick brown fox jumps over the lazy dog".toByteArray(StandardCharsets.UTF_8)
val cipherEnc = Cipher.getInstance("ECIES")
cipherEnc.init(Cipher.ENCRYPT_MODE, keyPair.public) // In practice, the public key of the recipient side is used
val ciphertext = cipherEnc.doFinal(plaintext)
// Decryption
val cipherDec = Cipher.getInstance("ECIES")
cipherDec.init(Cipher.DECRYPT_MODE, keyPair.private)
val decrypted = cipherDec.doFinal(ciphertext)
println(String(decrypted, StandardCharsets.UTF_8))
API seviyesi 28 / Android 9 Pie ile test edildi.
Kullanılan algoritmalar üzerinde daha fazla kontrole sahip olmak istiyorsanız, tek tek bileşenler manuel olarak uygulanabilir, örn.
- Paylaşılan sırrı belirlemek için NIST P-521 ile ECDH
- AES-256 anahtarını karmanın ilk 32 baytı olarak belirlemek için SHA-512 (ECIES bağlamında olduğu gibi bir KDF kullanımı için de buraya bakın )
- Simetrik şifreleme için AES-256 / GCM ( GCM zaten kimliği doğrulanmış şifrelemedir, bu nedenle açık bir MAC gerekli değildir)
Aşağıdaki Kotlin kodu daha sonra bu bileşenlerle bir şifreleme / şifre çözme gerçekleştirir:
// Generate Keys
val keyPairA = generateKeyPair()
val keyPairB = generateKeyPair()
// Generate shared secrets
val sharedSecretA = getSharedSecret(keyPairA.private, keyPairB.public)
val sharedSecretB = getSharedSecret(keyPairB.private, keyPairA.public)
// Generate AES-keys
val aesKeyA = getAESKey(sharedSecretA)
val aesKeyB = getAESKey(sharedSecretB)
// Encryption (WLOG by A)
val plaintextA = "The quick brown fox jumps over the lazy dog".toByteArray(StandardCharsets.UTF_8)
val ciphertextA = encrypt(aesKeyA, plaintextA)
// Decryption (WLOG by B)
val plaintextB = decrypt(aesKeyB, ciphertextA)
println(String(plaintextB, StandardCharsets.UTF_8))
ile:
private fun generateKeyPair(): KeyPair {
val keyPairGenerator = KeyPairGenerator.getInstance("EC")
keyPairGenerator.initialize(ECGenParameterSpec("secp521r1"))
return keyPairGenerator.generateKeyPair()
}
private fun getSharedSecret(privateKey: PrivateKey, publicKey: PublicKey): ByteArray {
val keyAgreement = KeyAgreement.getInstance("ECDH")
keyAgreement.init(privateKey)
keyAgreement.doPhase(publicKey, true)
return keyAgreement.generateSecret()
}
private fun getAESKey(sharedSecret: ByteArray): ByteArray {
val digest = MessageDigest.getInstance("SHA-512")
return digest.digest(sharedSecret).copyOfRange(0, 32)
}
private fun encrypt(aesKey: ByteArray, plaintext: ByteArray): ByteArray {
val secretKeySpec = SecretKeySpec(aesKey, "AES")
val iv = ByteArray(12) // Create random IV, 12 bytes for GCM
SecureRandom().nextBytes(iv)
val gCMParameterSpec = GCMParameterSpec(128, iv)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, gCMParameterSpec)
val ciphertext = cipher.doFinal(plaintext)
val ivCiphertext = ByteArray(iv.size + ciphertext.size) // Concatenate IV and ciphertext (the MAC is implicitly appended to the ciphertext)
System.arraycopy(iv, 0, ivCiphertext, 0, iv.size)
System.arraycopy(ciphertext, 0, ivCiphertext, iv.size, ciphertext.size)
return ivCiphertext
}
private fun decrypt(aesKey: ByteArray, ivCiphertext: ByteArray): ByteArray {
val secretKeySpec = SecretKeySpec(aesKey, "AES")
val iv = ivCiphertext.copyOfRange(0, 12) // Separate IV
val ciphertext = ivCiphertext.copyOfRange(12, ivCiphertext.size) // Separate ciphertext (the MAC is implicitly separated from the ciphertext)
val gCMParameterSpec = GCMParameterSpec(128, iv)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, gCMParameterSpec)
return cipher.doFinal(ciphertext)
}
API Level 28 / Android 9 Pie ile tekrar test edildi.