ecDecrypt function
Decrypt a ciphertext for a given private key using ECIES algorithm @param {String | Uint8List} ciphertext Ciphertext to decrypt @param {String | Uint8List} privateKey Private key for the shared secret encryption
Implementation
Uint8List ecDecrypt(
dynamic cipherText,
dynamic privateKey, {
bool isCipherTextHexa = true,
bool isPrivateKeyHexa = true,
}) {
if (cipherText is! Uint8List && cipherText is! String) {
throw "'cipherText' must be a string or Uint8List";
}
if (privateKey is! List<int> && privateKey is! String) {
throw "'publicKey' must be a string or Uint8List";
}
if (cipherText is String) {
if (isCipherTextHexa && !isHex(cipherText)) {
throw const FormatException("'cipherText' must be an hexadecimal string");
}
if (isCipherTextHexa) {
cipherText = Uint8List.fromList(hexToUint8List(cipherText));
} else {
cipherText = Uint8List.fromList(utf8.encode(cipherText));
}
}
if (privateKey is String) {
if (isPrivateKeyHexa && !isHex(privateKey)) {
throw const FormatException("'privateKey' must be an hexadecimal string");
}
if (isPrivateKeyHexa) {
privateKey = Uint8List.fromList(hexToUint8List(privateKey));
} else {
throw "'privateKey' must be an hexadecimal string";
}
}
final curveBuf = Uint8List.fromList(privateKey.sublist(0, 1));
final pvBuf = Uint8List.fromList(privateKey.sublist(2, privateKey.length));
switch (curveBuf[0]) {
case 0:
final Uint8List ephemeralPubKey = cipherText.sublist(0, 32);
final Uint8List tag = cipherText.sublist(32, 32 + 16);
final Uint8List encrypted =
cipherText.sublist(32 + 16, cipherText.length);
final curve25519pv = Uint8List(32);
tweetnacl.TweetNaClExt.crypto_sign_ed25519_sk_to_x25519_sk(
curve25519pv,
pvBuf,
);
final sharedKey = x25519.X25519(curve25519pv, ephemeralPubKey);
final secret = deriveSecret(sharedKey);
return aesAuthDecrypt(
encrypted,
Uint8List.fromList(secret.aesKey!),
Uint8List.fromList(secret.iv!),
tag,
);
case 1:
final Uint8List ephemeralPubKey = cipherText.sublist(0, 65);
final Uint8List tag = cipherText.sublist(65, 65 + 16);
final Uint8List encrypted =
cipherText.sublist(65 + 16, cipherText.length);
final ec = elliptic.getP256();
final privateKey = elliptic.PrivateKey.fromBytes(ec, pvBuf);
final publicKey =
elliptic.PublicKey.fromHex(ec, uint8ListToHex(ephemeralPubKey));
final sharedKey =
Uint8List.fromList(ecdh.computeSecret(privateKey, publicKey));
final secret = deriveSecret(sharedKey);
return aesAuthDecrypt(
encrypted,
Uint8List.fromList(secret.aesKey!),
Uint8List.fromList(secret.iv!),
tag,
);
case 2:
final Uint8List ephemeralPubKey = cipherText.sublist(0, 65);
final Uint8List tag = cipherText.sublist(65, 65 + 16);
final Uint8List encrypted =
cipherText.sublist(65 + 16, cipherText.length);
final ec = elliptic.getSecp256k1();
final privateKey = elliptic.PrivateKey.fromBytes(ec, pvBuf);
final publicKey =
elliptic.PublicKey.fromHex(ec, uint8ListToHex(ephemeralPubKey));
final sharedKey =
Uint8List.fromList(ecdh.computeSecret(privateKey, publicKey));
final secret = deriveSecret(sharedKey);
return aesAuthDecrypt(
encrypted,
Uint8List.fromList(secret.aesKey!),
Uint8List.fromList(secret.iv!),
tag,
);
default:
throw 'Curve not supported';
}
}