feat: Enhance avatar management with detailed logging and error handling
This commit is contained in:
@@ -411,29 +411,30 @@ object CryptoManager {
|
||||
*/
|
||||
fun encrypt(data: String, publicKeyHex: String): String {
|
||||
val ecSpec = ECNamedCurveTable.getParameterSpec("secp256k1")
|
||||
val keyPairGenerator = KeyPairGenerator.getInstance("ECDH", BouncyCastleProvider.PROVIDER_NAME)
|
||||
keyPairGenerator.initialize(ecSpec, SecureRandom())
|
||||
|
||||
// Generate ephemeral key pair
|
||||
val ephemeralKeyPair = keyPairGenerator.generateKeyPair()
|
||||
val ephemeralPrivateKey = ephemeralKeyPair.private as org.bouncycastle.jce.interfaces.ECPrivateKey
|
||||
val ephemeralPublicKey = ephemeralKeyPair.public as org.bouncycastle.jce.interfaces.ECPublicKey
|
||||
// Generate ephemeral private key (random 32 bytes)
|
||||
val ephemeralPrivateKeyBytes = ByteArray(32)
|
||||
SecureRandom().nextBytes(ephemeralPrivateKeyBytes)
|
||||
val ephemeralPrivateKeyBigInt = BigInteger(1, ephemeralPrivateKeyBytes)
|
||||
|
||||
// Generate ephemeral public key from private key
|
||||
val ephemeralPublicKeyPoint = ecSpec.g.multiply(ephemeralPrivateKeyBigInt)
|
||||
|
||||
// Parse recipient's public key
|
||||
val recipientPublicKeyBytes = publicKeyHex.chunked(2).map { it.toInt(16).toByte() }.toByteArray()
|
||||
val recipientPublicKeyPoint = ecSpec.curve.decodePoint(recipientPublicKeyBytes)
|
||||
val recipientPublicKeySpec = ECPublicKeySpec(recipientPublicKeyPoint, ecSpec)
|
||||
val keyFactory = KeyFactory.getInstance("ECDH", BouncyCastleProvider.PROVIDER_NAME)
|
||||
val recipientPublicKey = keyFactory.generatePublic(recipientPublicKeySpec)
|
||||
|
||||
// Compute shared secret using ECDH
|
||||
val keyAgreement = javax.crypto.KeyAgreement.getInstance("ECDH", BouncyCastleProvider.PROVIDER_NAME)
|
||||
keyAgreement.init(ephemeralPrivateKey)
|
||||
keyAgreement.doPhase(recipientPublicKey, true)
|
||||
val sharedSecret = keyAgreement.generateSecret()
|
||||
// Compute shared secret using ECDH (ephemeralPrivateKey × recipientPublicKey)
|
||||
val sharedPoint = recipientPublicKeyPoint.multiply(ephemeralPrivateKeyBigInt).normalize()
|
||||
|
||||
// Use first 32 bytes (x-coordinate) as AES key
|
||||
val sharedKey = sharedSecret.copyOfRange(1, 33)
|
||||
// Use x-coordinate of shared point as AES key (32 bytes)
|
||||
val sharedKeyBytes = sharedPoint.affineXCoord.encoded
|
||||
val sharedKey = if (sharedKeyBytes.size >= 32) {
|
||||
sharedKeyBytes.copyOfRange(sharedKeyBytes.size - 32, sharedKeyBytes.size)
|
||||
} else {
|
||||
// Pad with leading zeros if needed
|
||||
ByteArray(32 - sharedKeyBytes.size) + sharedKeyBytes
|
||||
}
|
||||
val key = SecretKeySpec(sharedKey, "AES")
|
||||
|
||||
// Generate random IV
|
||||
@@ -446,8 +447,7 @@ object CryptoManager {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec)
|
||||
val encrypted = cipher.doFinal(data.toByteArray(Charsets.UTF_8))
|
||||
|
||||
// Get ephemeral private key bytes
|
||||
val ephemeralPrivateKeyBytes = ephemeralPrivateKey.d.toByteArray()
|
||||
// Normalize ephemeral private key to 32 bytes
|
||||
val normalizedPrivateKey = if (ephemeralPrivateKeyBytes.size > 32) {
|
||||
ephemeralPrivateKeyBytes.copyOfRange(ephemeralPrivateKeyBytes.size - 32, ephemeralPrivateKeyBytes.size)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user