feat: Enhance avatar management with detailed logging and error handling

This commit is contained in:
2026-01-24 00:26:23 +05:00
parent b08bea2c14
commit 1367864008
11 changed files with 107 additions and 324 deletions

View File

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