encrypt static method
Encrypts plaintext to recipientKemKey, returning a base64 envelope.
recipientKemKey comes from the recipient's published attestation.
senderPubkey and recipientPubkey must be 64-character lowercase hex
x-only pubkeys; they are bound into the AEAD so the ciphertext cannot be
replayed into a different conversation or have its direction swapped.
Implementation
static Future<String> encrypt({
required String plaintext,
required Uint8List recipientKemKey,
required String senderPrivateKey,
required String senderPubkey,
required String recipientPubkey,
}) async {
final conversationKey = _conversationKey(senderPrivateKey, recipientPubkey);
final msg = Uint8List.fromList(utf8.encode(plaintext));
final kemPtr = calloc<Uint8>(recipientKemKey.length);
final convPtr = calloc<Uint8>(conversationKey.length);
final msgPtr = calloc<Uint8>(msg.length);
final out = calloc<rust_lib.QsBuffer>();
final sender = senderPubkey.toNativeUtf8();
final recipient = recipientPubkey.toNativeUtf8();
try {
kemPtr.asTypedList(recipientKemKey.length).setAll(0, recipientKemKey);
convPtr.asTypedList(conversationKey.length).setAll(0, conversationKey);
msgPtr.asTypedList(msg.length).setAll(0, msg);
final ok = rust_lib.pqSeal(
kemPtr,
recipientKemKey.length,
convPtr,
conversationKey.length,
sender,
recipient,
msgPtr,
msg.length,
out,
);
if (ok != 1) throw StateError('Post-quantum encryption failed');
return utf8.decode(_copyOut(out));
} finally {
convPtr
.asTypedList(conversationKey.length)
.fillRange(0, conversationKey.length, 0);
msgPtr.asTypedList(msg.length).fillRange(0, msg.length, 0);
calloc.free(kemPtr);
calloc.free(convPtr);
calloc.free(msgPtr);
calloc.free(out);
calloc.free(sender);
calloc.free(recipient);
}
}