ecDecrypt function

Uint8List ecDecrypt(
  1. dynamic cipherText,
  2. dynamic privateKey, {
  3. bool isCipherTextHexa = true,
  4. bool isPrivateKeyHexa = true,
})

Decrypt a ciphertext for a given private key using ECIES algorithm

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';
  }
}