open method

Uint8List open(
  1. List<int> nonce,
  2. SealedBox box, {
  3. List<int> aad = const [],
})

Verifies and decrypts box. Throws AuthenticationException on any mismatch of key, nonce, AAD, ciphertext or tag.

Implementation

Uint8List open(List<int> nonce, SealedBox box, {List<int> aad = const []}) {
  initNoConfig();
  if (box.tag.length != tagLength) {
    throw const AuthenticationException();
  }
  return using((arena) {
    final ctx = _newCtx(arena, nonce, encrypt: false);
    try {
      final outl = arena<Int>();
      if (aad.isNotEmpty) {
        checkOne(
          ssl.EVP_DecryptUpdate(
            ctx,
            nullptr,
            outl,
            toNative(arena, aad),
            aad.length,
          ),
          'EVP_DecryptUpdate(aad)',
        );
      }
      // Holds unauthenticated plaintext until the tag verifies; wiped on
      // release whether or not it did.
      final out = secretBuffer(arena, box.ciphertext.length + 16);
      var produced = 0;
      if (box.ciphertext.isNotEmpty) {
        checkOne(
          ssl.EVP_DecryptUpdate(
            ctx,
            out,
            outl,
            toNative(arena, box.ciphertext),
            box.ciphertext.length,
          ),
          'EVP_DecryptUpdate',
        );
        produced = outl.value;
      }
      checkOne(
        ssl.EVP_CIPHER_CTX_ctrl(
          ctx,
          ssl.EVP_CTRL_AEAD_SET_TAG,
          tagLength,
          toNative(arena, box.tag).cast(),
        ),
        'EVP_CIPHER_CTX_ctrl(SET_TAG)',
      );
      final ok = ssl.EVP_DecryptFinal_ex(ctx, out + produced, outl);
      if (ok != 1) {
        ssl.ERR_clear_error();
        throw const AuthenticationException();
      }
      produced += outl.value;
      return fromNative(out, produced);
    } finally {
      ssl.EVP_CIPHER_CTX_free(ctx);
    }
  });
}