| .. | ||
| fluorine.js | 3.4K | |
| README.md | 1.8K |
🧪 fluorine.js - NIP-44 encryption
fluorine.js is a miniature nostr-tools nip44: NIP-44 v2 encryption in about 3.5kb of ChaCha20, HMAC-SHA256 and padding over crypto.subtle. It derives conversation keys through helium.js's ECDH, then encrypts and decrypts payloads that any NIP-44 client can read. Loaded after helium.js, it gives helium's local signer a nip44 face like a NIP-07 extension's, and chlorine.js and iodine.js use it for private messages and encrypted content.
<script src="helium.js"></script>
<script src="fluorine.js"></script>
<script type="module">
let box = await helium.signer.nip44.encrypt(theirPubkey, "meet at noon")
let text = await helium.signer.nip44.decrypt(theirPubkey, box)
</script>
The local key encrypts a message only it and the owner of theirPubkey can read, and decrypts it again.
API
| function | returns |
|---|---|
fluorine.key(sk, pk) |
conversation key (Uint8Array(32)) for a hex secret key and hex public key |
fluorine.encrypt(text, key, nonce?) |
base64 payload. nonce is a Uint8Array(32), random by default |
fluorine.decrypt(payload, key) |
plaintext, or throws on a bad version, length, MAC or padding |
fluorine.nip44(sk) |
NIP-07 shaped {encrypt(pk, text), decrypt(pk, payload)} for that key, caching conversation keys |
fluorine.pad(n) |
padded length for an n byte message |
helium.signer.nip44 |
{encrypt, decrypt} using helium.key(), added when helium.js is loaded first |
All functions return promises except nip44 and pad. Plaintext must be 1 to 65535 bytes of UTF-8.
Caveats
ECDH runs on helium's BigInt arithmetic, which is not constant time, and the local key lives in localStorage. Prefer an extension's nostr.nip44 for keys that matter. Tests check every official NIP-44 vector and round trips against nostr-tools.