diff --git a/sodium-native.d.ts b/sodium-native.d.ts
new file mode 100644
index 0000000..8cc209c
--- /dev/null
+++ b/sodium-native.d.ts
@@ -0,0 +1,29 @@
+declare module 'sodium-native' {
+ // Type definitions for sodium-native 4.x
+ // Minimal definitions for APIs used by lib-crypto-utils
+
+ ///
+
+ // Constants used by lib-crypto-utils
+ export const crypto_auth_BYTES: number
+ export const crypto_box_PUBLICKEYBYTES: number
+ export const crypto_box_SECRETKEYBYTES: number
+ export const crypto_scalarmult_BYTES: number
+ export const crypto_sign_BYTES: number
+ export const crypto_sign_PUBLICKEYBYTES: number
+ export const crypto_sign_SECRETKEYBYTES: number
+
+ // Functions used by lib-crypto-utils
+ export function randombytes_buf(buffer: Buffer): void
+ export function crypto_generichash(output: Buffer, input: Buffer, key?: Buffer): void
+ export function crypto_sign_keypair(publicKey: Buffer, secretKey: Buffer): void
+ export function crypto_sign_ed25519_sk_to_curve25519(curve_sk: Buffer, ed_sk: Buffer): void
+ export function crypto_sign_ed25519_pk_to_curve25519(curve_pk: Buffer, ed_pk: Buffer): void
+ export function crypto_auth(output: Buffer, input: Buffer, key: Buffer): void
+ export function crypto_auth_verify(output: Buffer, input: Buffer, key: Buffer): boolean
+ export function crypto_sign(signedMessage: Buffer, message: Buffer, secretKey: Buffer): void
+ export function crypto_sign_open(message: Buffer, signedMessage: Buffer, publicKey: Buffer): boolean
+ export function crypto_sign_detached(signature: Buffer, message: Buffer, secretKey: Buffer): void
+ export function crypto_sign_verify_detached(signature: Buffer, message: Buffer, publicKey: Buffer): boolean
+ export function crypto_scalarmult(sharedSecret: Buffer, secretKey: Buffer, remotePublicKey: Buffer): void
+}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index b67f000..9012e6d 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -323,8 +323,9 @@ export function setCustomStringifier(method: (input: unknown) => string, name: s
* Returns a signature obtained by signing the input hash (hex string or buffer) with the sk string
* @param input
* @param sk
+ * @param detached - If true (default), returns only the signature (64 bytes). If false, returns signature + message
*/
-export function sign(input: hexstring | Buffer, sk: secretKey | Buffer): string {
+export function sign(input: hexstring | Buffer, sk: secretKey | Buffer, detached = true): string {
let inputBuf: Buffer
let skBuf: Buffer
if (typeof input !== 'string') {
@@ -353,9 +354,65 @@ export function sign(input: hexstring | Buffer, sk: secretKey | Buffer): string
throw new TypeError('Secret key string must be in hex format')
}
}
- const sig = Buffer.allocUnsafe(inputBuf.length + sodium.crypto_sign_BYTES)
+ if (detached) {
+ // Use detached signature
+ const sig = Buffer.allocUnsafe(sodium.crypto_sign_BYTES)
+ try {
+ sodium.crypto_sign_detached(sig, inputBuf, skBuf)
+ } catch (e) {
+ throw new Error('Failed to sign input with provided secret key.')
+ }
+ return sig.toString('hex')
+ } else {
+ // Use non-detached signature (legacy behavior)
+ const sig = Buffer.allocUnsafe(inputBuf.length + sodium.crypto_sign_BYTES)
+ try {
+ sodium.crypto_sign(sig, inputBuf, skBuf)
+ } catch (e) {
+ throw new Error('Failed to sign input with provided secret key.')
+ }
+ return sig.toString('hex')
+ }
+}
+
+/**
+ * Returns a detached signature obtained by signing the input hash (hex string or buffer) with the sk string
+ * @param input - The message to sign (hex string or buffer)
+ * @param sk - The secret key
+ * @returns Only the 64-byte signature as hex string
+ */
+export function signDetached(input: hexstring | Buffer, sk: secretKey | Buffer): string {
+ let inputBuf: Buffer
+ let skBuf: Buffer
+ if (typeof input !== 'string') {
+ if (Buffer.isBuffer(input)) {
+ inputBuf = input
+ } else {
+ throw new TypeError('Input must be a hex string or buffer.')
+ }
+ } else {
+ try {
+ inputBuf = Buffer.from(input, 'hex')
+ } catch (e) {
+ throw new TypeError('Input string must be in hex format.')
+ }
+ }
+ if (typeof sk !== 'string') {
+ if (Buffer.isBuffer(sk)) {
+ skBuf = sk
+ } else {
+ throw new TypeError('Secret key must be a hex string or buffer.')
+ }
+ } else {
+ try {
+ skBuf = Buffer.from(sk, 'hex')
+ } catch (e) {
+ throw new TypeError('Secret key string must be in hex format')
+ }
+ }
+ const sig = Buffer.allocUnsafe(sodium.crypto_sign_BYTES)
try {
- sodium.crypto_sign(sig, inputBuf, skBuf)
+ sodium.crypto_sign_detached(sig, inputBuf, skBuf)
} catch (e) {
throw new Error('Failed to sign input with provided secret key.')
}
@@ -368,9 +425,33 @@ export function sign(input: hexstring | Buffer, sk: secretKey | Buffer): string
* @param obj
* @param sk
* @param pk
+ * @param detached - If true (default), uses detached signature (64 bytes only). If false, uses non-detached
+ * @returns the new signed object with the `sign` field. The original object is mutated as well.
+ */
+export function signObj(obj: object, sk: secretKey | Buffer, pk: publicKey | Buffer, detached = true): SignedObject {
+ if (typeof obj !== 'object') {
+ throw new TypeError('Input must be an object.')
+ }
+ // If it's an array, we don't want to try to sign it
+ if (Array.isArray(obj)) {
+ throw new TypeError('Input cannot be an array.')
+ }
+ const objStr = stringify(obj)
+ const hashed = hash(objStr, 'buffer')
+ const sig = sign(hashed, sk, detached)
+ const signPk = Buffer.isBuffer(pk) ? bufferToHex(pk) : pk
+ ;(obj as SignedObject).sign = { owner: signPk, sig }
+ return obj as SignedObject
+}
+
+/**
+ * Attaches a sign field to the input object using detached signatures
+ * @param obj - The object to sign
+ * @param sk - The secret key
+ * @param pk - The public key
* @returns the new signed object with the `sign` field. The original object is mutated as well.
*/
-export function signObj(obj: object, sk: secretKey | Buffer, pk: publicKey | Buffer): SignedObject {
+export function signObjDetached(obj: object, sk: secretKey | Buffer, pk: publicKey | Buffer): SignedObject {
if (typeof obj !== 'object') {
throw new TypeError('Input must be an object.')
}
@@ -380,7 +461,7 @@ export function signObj(obj: object, sk: secretKey | Buffer, pk: publicKey | Buf
}
const objStr = stringify(obj)
const hashed = hash(objStr, 'buffer')
- const sig = sign(hashed, sk)
+ const sig = signDetached(hashed, sk)
const signPk = Buffer.isBuffer(pk) ? bufferToHex(pk) : pk
;(obj as SignedObject).sign = { owner: signPk, sig }
return obj as SignedObject
@@ -402,13 +483,59 @@ function verify(msg: string, sig: hexstring | Buffer, pk: publicKey | Buffer): b
}
const sigBuf = _ensureBuffer(sig)
const pkBuf = _ensureBuffer(pk)
+
+ // Auto-detect signature type based on length
+ // Detached signatures are exactly 64 bytes
+ // Non-detached signatures are 64 bytes + message length
+ const msgBuf = Buffer.from(msg, 'hex')
+ const expectedNonDetachedLength = sodium.crypto_sign_BYTES + msgBuf.length
+
+ if (sigBuf.length === sodium.crypto_sign_BYTES) {
+ // This is a detached signature
+ try {
+ return sodium.crypto_sign_verify_detached(sigBuf as Buffer, msgBuf, pkBuf as Buffer)
+ } catch (e) {
+ return false
+ }
+ } else if (sigBuf.length === expectedNonDetachedLength) {
+ // This is a non-detached signature
+ try {
+ const opened = Buffer.allocUnsafe(sigBuf.length - sodium.crypto_sign_BYTES)
+ sodium.crypto_sign_open(opened, sigBuf as Buffer, pkBuf as Buffer)
+ const verified = opened.toString('hex')
+ return verified === msg
+ } catch (e) {
+ return false
+ }
+ } else {
+ // Invalid signature length
+ throw new Error('Invalid signature length. Expected either detached (64 bytes) or non-detached signature.')
+ }
+}
+
+/**
+ * Verifies a detached signature against a message
+ * @param msg - The message that was signed (hex string)
+ * @param sig - The detached signature (hex string or buffer)
+ * @param pk - The public key to verify with
+ * @returns true if the signature is valid, false otherwise
+ */
+export function verifyDetached(msg: string, sig: hexstring | Buffer, pk: publicKey | Buffer): boolean {
+ if (typeof msg !== 'string') {
+ throw new TypeError('Message to compare must be a string.')
+ }
+ const msgBuf = Buffer.from(msg, 'hex')
+ const sigBuf = _ensureBuffer(sig)
+ const pkBuf = _ensureBuffer(pk)
+
+ if (sigBuf.length !== sodium.crypto_sign_BYTES) {
+ throw new Error('Invalid signature length for detached signature.')
+ }
+
try {
- const opened = Buffer.allocUnsafe(sigBuf.length - sodium.crypto_sign_BYTES)
- sodium.crypto_sign_open(opened, sigBuf as Buffer, pkBuf as Buffer)
- const verified = opened.toString('hex')
- return verified === msg
+ return sodium.crypto_sign_verify_detached(sigBuf as Buffer, msgBuf, pkBuf as Buffer)
} catch (e) {
- throw new Error('Unable to verify provided signature with provided public key.')
+ return false
}
}
@@ -433,6 +560,28 @@ export function verifyObj(obj: SignedObject): boolean {
return verify(objHash, obj.sign.sig, obj.sign.owner)
}
+/**
+ * Verifies an object signed with detached signature
+ * @param obj - The signed object to verify
+ * @returns true if the signature is valid, false otherwise
+ */
+export function verifyObjDetached(obj: SignedObject): boolean {
+ if (typeof obj !== 'object') {
+ throw new TypeError('Input must be an object.')
+ }
+ if (!obj.sign || !obj.sign.owner || !obj.sign.sig) {
+ throw new Error('Object must contain a sign field with the following data: { owner, sig }')
+ }
+ if (typeof obj.sign.owner !== 'string') {
+ throw new TypeError('Owner must be a public key represented as a hex string.')
+ }
+ if (typeof obj.sign.sig !== 'string') {
+ throw new TypeError('Signature must be a valid signature represented as a hex string.')
+ }
+ const objHash = hashObj(obj, true)
+ return verifyDetached(objHash, obj.sign.sig, obj.sign.owner)
+}
+
/**
* This function initialized the cryptographic hashing functions
* @param key The HASH_KEY for initializing the cryptographic hashing functions
diff --git a/src/sodium-native/index.d.ts b/src/sodium-native/index.d.ts
deleted file mode 100644
index 66f8ed6..0000000
--- a/src/sodium-native/index.d.ts
+++ /dev/null
@@ -1,1300 +0,0 @@
-declare module 'sodium-native' {
- // Type definitions for sodium-native 2.3
- // Project: https://github.com/sodium-friends/sodium-native
- // Definitions by: Florian Keller
- // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
-
- ///
-
- export interface CryptoGenericHashWrap {
- /**
- * Update the instance with a new piece of data.
- *
- * * `input` should be a buffer of any size.
- */
- update(input: Buffer): void
-
- /**
- * Finalize the instance.
- *
- * * `output` should be a buffer as above with the same length you gave when creating the instance.
- *
- * The generated hash is stored in `output`.
- */
- final(output: Buffer): void
- }
-
- export interface CryptoStreamChacha20XorWrap {
- /**
- * Encrypt the next message
- */
- update(ciphertext: Buffer, message: Buffer): void
-
- /**
- * Finalize the stream. Zeros out internal state.
- */
- final(): void
- }
-
- export interface Xchacha20poly1305State {
- _pad: Buffer
- nonce: Buffer
- k: Buffer
- }
-
- export interface CryptoOneTimeAuthWrap {
- /**
- * Update the instance with a new piece of data.
- *
- * * `input` should be a buffer of any size.
- */
- update(input: Buffer): void
-
- /**
- * Finalize the instance.
- *
- * * `output` should be a buffer of length `crypto_onetimeauth_BYTES`.
- *
- * The generated hash is stored in `output`.
- */
- final(output: Buffer): void
- }
-
- export interface CryptoHashSha256Wrap {
- /**
- * Update the instance with a new piece of data.
- *
- * * `input` should be a buffer of any size.
- */
- update(input: Buffer): void
-
- /**
- * Finalize the instance.
- *
- * * `output` should be a buffer of length `crypto_hash_sha256_BYTES`.
- *
- * The generated hash is stored in `output`.
- */
- final(output: Buffer): void
- }
-
- export const crypto_aead_xchacha20poly1305_ietf_ABYTES: number
- export const crypto_aead_xchacha20poly1305_ietf_KEYBYTES: number
- /** Note this is `Number.MAX_SAFE_INTEGER` for now */
- export const crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX: number
- export const crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: number
- export const crypto_aead_xchacha20poly1305_ietf_NSECBYTES: number
- export const crypto_core_ed25519_BYTES: number
- export const crypto_core_ed25519_NONREDUCEDSCALARBYTES: number
- export const crypto_core_ed25519_SCALARBYTES: number
- export const crypto_core_ed25519_UNIFORMBYTES: number
- export const crypto_secretstream_xchacha20poly1305_ABYTES: number
- export const crypto_secretstream_xchacha20poly1305_HEADERBYTES: number
- export const crypto_generichash_BYTES_MAX: number
- export const crypto_generichash_BYTES_MIN: number
- export const crypto_generichash_BYTES: number
- export const crypto_generichash_KEYBYTES_MAX: number
- export const crypto_generichash_KEYBYTES_MIN: number
- export const crypto_generichash_KEYBYTES: number
- export const crypto_pwhash_ALG_ARGON2I13: number
- export const crypto_pwhash_ALG_ARGON2ID13: number
- export const crypto_pwhash_ALG_DEFAULT: number
- export const crypto_pwhash_MEMLIMIT_INTERACTIVE: number
- export const crypto_pwhash_MEMLIMIT_MODERATE: number
- export const crypto_pwhash_MEMLIMIT_SENSITIVE: number
- export const crypto_pwhash_OPSLIMIT_INTERACTIVE: number
- export const crypto_pwhash_OPSLIMIT_MODERATE: number
- export const crypto_pwhash_OPSLIMIT_SENSITIVE: number
- export const crypto_scalarmult_ed25519_BYTES: number
- export const crypto_secretstream_xchacha20poly1305_KEYBYTES: number
- export const crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX: number
- export const crypto_scalarmult_ed25519_SCALARBYTES: number
- export const crypto_secretstream_xchacha20poly1305_TAG_FINAL: number
- export const crypto_secretstream_xchacha20poly1305_TAG_MESSAGE: number
- export const crypto_secretstream_xchacha20poly1305_TAG_PUSH: number
- export const crypto_secretstream_xchacha20poly1305_TAG_REKEY: number
- export const crypto_sign_PUBLICKEYBYTES: number
- export const crypto_sign_SECRETKEYBYTES: number
- export const crypto_sign_BYTES: number
- export const crypto_sign_SEEDBYTES: number
- export const crypto_auth_BYTES: number
- export const crypto_auth_KEYBYTES: number
- export const crypto_scalarmult_BYTES: number
- export const crypto_scalarmult_SCALARBYTES: number
- /** NOTE: Unofficial constant */
- export const crypto_secretstream_xchacha20poly1305_TAGBYTES: number
- export const crypto_box_SEALBYTES: number
- export const crypto_box_PUBLICKEYBYTES: number
- export const crypto_box_SECRETKEYBYTES: number
- export const crypto_box_MACBYTES: number
- export const crypto_box_NONCEBYTES: number
-
- /**
- * Zero out the data in `buffer`.
- */
- export function sodium_memzero(buffer: Buffer): void
-
- /**
- * Lock the memory contained in `buffer`.
- */
- export function sodium_mlock(buffer: Buffer): void
-
- /**
- * Unlock previously `sodium_mlock`ed memory contained in `buffer`. This will also `sodium_memzero` `buffer`.
- */
- export function sodium_munlock(buffer: Buffer): void
-
- /**
- * Allocate a buffer of `size` which is memory protected. See [libsodium docs](https://download.libsodium.org/doc/memory_management#guarded-heap-allocations) for details. Be aware that many Buffer
- * methods may break the security guarantees of `sodium.sodium_malloc`'ed memory. To check if a `Buffer` is a "secure" buffer, you can call access the getter `buffer.secure` which will be `true`.
- */
- export function sodium_malloc(size: number): Buffer
-
- /**
- * Make `buffer` allocated using `sodium.sodium_malloc` inaccessible, crashing the process if any access is attempted.
- * Note that this will have no effect for normal `Buffer`s.
- */
- export function sodium_mprotect_noaccess(buffer: Buffer): void
-
- /**
- * Make `buffer` allocated using `sodium.sodium_malloc` read-only, crashing the process if any writing is attempted.
- * Note that this will have no effect for normal `Buffer`s.
- */
- export function sodium_mprotect_readonly(buffer: Buffer): void
-
- /**
- * Make `buffer` allocated using `sodium.sodium_malloc` read-write, undoing `sodium_mprotect_noaccess` or `sodium_mprotect_readonly`.
- * Note that this will have no effect for normal `Buffer`s.
- */
- export function sodium_mprotect_readwrite(buffer: Buffer): void
-
- /**
- * Generate a random 32-bit unsigned integer `[0, 0xffffffff]` (both inclusive)
- */
- export function randombytes_random(): number
-
- /**
- * Generate a random 32-bit unsigned integer `[0, upper_bound)` (last exclusive).
- * `upper_bound` must be `0xffffffff` at most.
- */
- export function randombytes_uniform(upper_bound: number): number
-
- /**
- * Fill `buffer` with random data.
- */
- export function randombytes_buf(buffer: Buffer): void
-
- /**
- * Fill `buffer` with random data, generated from `seed`.
- * `seed` must be a Buffer of at least `sodium.randombytes_SEEDBYTES` length
- */
- export function randombytes_buf_deterministic(buffer: Buffer, seed: Buffer): void
-
- /**
- * Compare `b1` with `b2`, in **constant-time** for `b1.length`.
- *
- * * `b1` must be `Buffer`
- * * `b2` must be `Buffer` and must be `b1.length` bytes
- *
- * Returns `true` when equal, otherwise `false`.
- */
- export function sodium_memcmp(b1: Buffer, b2: Buffer): boolean
-
- /**
- * Compare `b1` with `b2`, regarding either as little-endian encoded number.
- *
- * * `b1` must be `Buffer`
- * * `b2` must be `Buffer` and must be `b1.length` bytes
- *
- * Returns `1`, `0` or `-1` on whether `b1` is greater, equal or less than `b2`.
- * This is the same scheme as `Array.prototype.sort` expect.
- */
- export function sodium_compare(b1: Buffer, b2: Buffer): 1 | 0 | -1
-
- /**
- * Adds `b` to `a` (wrapping), regarding either as little-endian encoded number,
- * and writing the result into `a`.
- *
- * * `a` must be `Buffer`
- * * `b` must be `Buffer` and must be `a.length` bytes
- */
- export function sodium_add(a: Buffer, b: Buffer): void
-
- /**
- * Subtracts `b` from `a` (wrapping), regarding either as little-endian encoded
- * number, and writing the result into `a`.
- *
- * * `a` must be `Buffer`
- * * `b` must be `Buffer` and must be `a.length` bytes
- */
- export function sodium_sub(a: Buffer, b: Buffer): void
-
- /**
- * Increment `buf` as a little-endian number. This operation is **constant-time**
- * for the length of `buf`.
- *
- * * `buf` must be `Buffer`
- */
- export function sodium_increment(buf: Buffer): void
-
- /**
- * Test whether `buf` is all zero for `len` bytes. This operation is
- * **constant-time** for `len`.
- *
- * * `len` must be integer at most the length of `buf`
- *
- * Returns `true` if all `len` bytes are zero, otherwise `false`.
- */
- export function sodium_is_zero(buf: Buffer, len: number): boolean
-
- /**
- * Pad `buf` with random data from index `unpaddedLength` up to closest multiple of
- * `blocksize`.
- *
- * * `buf` must be `Buffer`
- * * `unpadded_buflen` must be integer at most `buf.length`
- * * `blocksize` must be integer greater than 1 but at most `buf.length`
- *
- * Returns the length of the padded data (so you may `.slice` the buffer to here).
- */
- export function sodium_pad(buf: Buffer, unpaddedLength: number, blocksize: number): number
-
- /**
- * Calculate `unpaddedLength` from a padded `buf` with `blocksize`
- *
- * * `buf` must be `Buffer`
- * * `padded_buflen` must be integer at most `buf.length`
- * * `blocksize` must be integer greater than 1 but at most `buf.length`
- *
- * Returns the length of the unpadded data (so you may `.slice` the buffer to here).
- */
- export function sodium_unpad(buf: Buffer, paddedLength: number, blocksize: number): number
-
- /**
- * Create a new keypair based on a seed.
- *
- * * `publicKey` should be a buffer with length `crypto_sign_PUBLICKEYBYTES`.
- * * `secretKey` should be a buffer with length `crypto_sign_SECRETKEYBYTES`.
- * * `seed` should be a buffer with length `crypto_sign_SEEDBYTES`.
- *
- * The generated public and secret key will be stored in passed in buffers.
- */
- export function crypto_sign_seed_keypair(publicKey: Buffer, secretKey: Buffer, seed: Buffer): void
-
- /**
- * Create a new keypair.
- *
- * * `publicKey` should be a buffer with length `crypto_sign_PUBLICKEYBYTES`.
- * * `secretKey` should be a buffer with length `crypto_sign_SECRETKEYBYTES`.
- *
- * The generated public and secret key will be stored in passed in buffers.
- */
- export function crypto_sign_keypair(publicKey: Buffer, secretKey: Buffer): void
-
- /**
- * Sign a message.
- *
- * * `signedMessage` should be a buffer with length `crypto_sign_BYTES + message.length`.
- * * `message` should be a buffer of any length.
- * * `secretKey` should be a secret key.
- *
- * The generated signed message will be stored in `signedMessage`.
- */
- export function crypto_sign(signedMessage: Buffer, message: Buffer, secretKey: Buffer): void
-
- /**
- * Verify and open a message.
- *
- * * `message` should be a buffer with length `signedMessage.length - crypto_sign_BYTES`.
- * * `signedMessage` at least `crypto_sign_BYTES` length.
- * * `publicKey` should be a public key.
- *
- * Will return `true` if the message could be verified. Otherwise `false`.
- * If verified the originally signed message is stored in the `message` buffer.
- */
- export function crypto_sign_open(message: Buffer, signedMessage: Buffer, publicKey: Buffer): boolean
-
- /**
- * Same as `crypto_sign` except it only stores the signature.
- *
- * * `signature` should be a buffer with length `crypto_sign_BYTES`.
- * * `message` should be a buffer of any length.
- * * `secretKey` should be a secret key.
- *
- * The generated signature is stored in `signature`.
- */
- export function crypto_sign_detached(signature: Buffer, message: Buffer, secretKey: Buffer): void
-
- /**
- * Verify a signature.
- *
- * * `signature` should be a buffer with length `crypto_sign_BYTES`.
- * * `message` should be a buffer of any length.
- * * `publicKey` should be a public key.
- *
- * Will return `true` if the message could be verified. Otherwise `false`.
- */
- export function crypto_sign_verify_detached(signature: Buffer, message: Buffer, publicKey: Buffer): boolean
-
- /**
- * Convert an ed25519 public key to curve25519 (which can be used with `box` and `scalarmult`)
- *
- * * `curve_pk` should be a buffer with length `crypto_box_PUBLICKEYBYTES`
- * * `ed_pk` should be a buffer with length `crypto_sign_PUBLICKEYBYTES`
- */
- export function crypto_sign_ed25519_pk_to_curve25519(curve_pk: Buffer, ed_pk: Buffer): void
-
- /**
- * Convert an ed25519 secret key to curve25519 (which can be used with `box` and `scalarmult`)
- *
- * * `curve_sk` should be a buffer with length `crypto_box_SECRETKEYBYTES`
- * * `ed_sk` should be a buffer with length `crypto_sign_SECRETKEYBYTES`
- */
- export function crypto_sign_ed25519_sk_to_curve25519(curve_sk: Buffer, ed_sk: Buffer): void
-
- /**
- * Extract an ed25519 public key from an ed25519 secret key
- *
- * * `pk` must be `Buffer` of at least `crypto_sign_PUBLICKEYBYTES` bytes
- * * `sk` must be `Buffer` of at least `crypto_sign_SECRETKEYBYTES` bytes
- */
- export function crypto_sign_ed25519_sk_to_pk(pk: Buffer, sk: Buffer): void
-
- /**
- * Hash a value with an optional key using the generichash method.
- *
- * * `output` should be a buffer with length within `crypto_generichash_BYTES_MIN` - `crypto_generichash_BYTES_MAX`.
- * * `input` should be a buffer of any length.
- * * `key` is an optional buffer of length within `crypto_generichash_KEYBYTES_MIN` - `crypto_generichash_KEYBYTES_MAX`.
- *
- * The generated hash is stored in `output`.
- *
- * Also exposes `crypto_generichash_BYTES` and `crypto_generichash_KEYBYTES` that can be used as "default" buffer sizes.
- */
- export function crypto_generichash(output: Buffer, input: Buffer, key?: Buffer): void
-
- /**
- * Same as `crypto_generichash` except this hashes an array of buffers instead of a single one.
- */
- export function crypto_generichash_batch(output: Buffer, inputArray: Buffer[], key?: Buffer): void
-
- /**
- * Create a generichash instance that can hash a stream of input buffers.
- *
- * * `key` is an optional buffer as above.
- * * `outputLength` the buffer size of your output.
- */
- export function crypto_generichash_instance(key?: Buffer, outputLength?: number): CryptoGenericHashWrap
-
- /**
- * Create a new keypair based on a seed.
- *
- * * `publicKey` should be a buffer with length `crypto_box_PUBLICKEYBYTES`.
- * * `secretKey` should be a buffer with length `crypto_box_SECRETKEYBYTES`.
- * * `seed` should be a buffer with length `crypto_box_SEEDBYTES`.
- *
- * The generated public and secret key will be stored in passed in buffers.
- */
- export function crypto_box_seed_keypair(publicKey: Buffer, secretKey: Buffer, seed: Buffer): void
-
- /**
- * Create a new keypair.
- *
- * * `publicKey` should be a buffer with length `crypto_box_PUBLICKEYBYTES`.
- * * `secretKey` should be a buffer with length `crypto_box_SECRETKEYBYTES`.
- *
- * The generated public and secret key will be stored in passed in buffers.
- */
- export function crypto_box_keypair(publicKey: Buffer, secretKey: Buffer): void
-
- /**
- * Encrypt a message.
- *
- * * `ciphertext` should be a buffer with length `message.length`.
- * * `mac` should be a buffer with length `crypto_box_MACBYTES`.
- * * `message` should be a buffer of any length.
- * * `nonce` should be a buffer with length `crypto_box_NONCEBYTES`.
- * * `publicKey` should be a public key.
- * * `secretKey` should be a secret key.
- *
- * The encrypted message will be stored in `ciphertext` and the authentification code will be stored in `mac`.
- */
- export function crypto_box_detached(
- ciphertext: Buffer,
- mac: Buffer,
- message: Buffer,
- nonce: Buffer,
- publicKey: Buffer,
- secretKey: Buffer
- ): void
-
- /**
- * Same as `crypto_box_detached` except it encodes the mac in the message.
- *
- * * `ciphertext` should be a buffer with length `message.length + crypto_box_MACBYTES`.
- * * `message` should be a buffer of any length.
- * * `nonce` should be a buffer with length `crypto_box_NONCEBYTES`.
- * * `publicKey` should be a public key.
- * * `secretKey` should be a secret key.
- *
- * The encrypted message and authentification code will be stored in `ciphertext`.
- */
- export function crypto_box_easy(
- ciphertext: Buffer,
- message: Buffer,
- nonce: Buffer,
- publicKey: Buffer,
- secretKey: Buffer
- ): void
-
- /**
- * Decrypt a message.
- *
- * * `message` should be a buffer with length `ciphertext.length`.
- * * `mac` should be a buffer with length `crypto_box_MACBYTES`.
- * * `ciphertext` should be a buffer of any length.
- * * `nonce` should be a buffer with length `crypto_box_NONCEBYTES`.
- * * `publicKey` should be a public key.
- * * `secretKey` should be a secret key.
- *
- * Returns `true` if the message could be decrypted. Otherwise `false`.
- *
- * The decrypted message will be stored in `message`.
- */
- export function crypto_box_open_detached(
- message: Buffer,
- ciphertext: Buffer,
- mac: Buffer,
- nonce: Buffer,
- publicKey: Buffer,
- secretKey: Buffer
- ): boolean
-
- /**
- * Decrypt a message encoded with the easy method.
- *
- * * `message` should be a buffer with length `ciphertext.length - crypto_box_MACBYTES`.
- * * `ciphertext` should be a buffer with length at least `crypto_box_MACBYTES`.
- * * `nonce` should be a buffer with length `crypto_box_NONCEBYTES`.
- * * `publicKey` should be a public key.
- * * `secretKey` should be a secret key.
- *
- * Returns `true` if the message could be decrypted. Otherwise `false`.
- *
- * The decrypted message will be stored in `message`.
- */
- export function crypto_box_open_easy(
- message: Buffer,
- ciphertext: Buffer,
- nonce: Buffer,
- publicKey: Buffer,
- secretKey: Buffer
- ): boolean
-
- /**
- * Encrypt a message in a sealed box using a throwaway keypair.
- * The ciphertext cannot be associated with the sender due to the sender's key
- * being a single use keypair that is overwritten during encryption.
- *
- * * `ciphertext` should be a buffer with length at least `message.length + crypto_box_SEALBYTES`.
- * * `message` should be a buffer with any length.
- * * `publicKey` should be the receipent's public key.
- */
- export function crypto_box_seal(ciphertext: Buffer, message: Buffer, publicKey: Buffer): void
-
- /**
- * Decrypt a message encoded with the sealed box method.
- *
- * * `message` should be a buffer with length at least `ciphertext.length - crypto_box_SEALBYTES`.
- * * `ciphertext` should be a buffer with length at least `crypto_box_SEALBYTES`.
- * * `publicKey` should be the receipient's public key.
- * * `secretKey` should be the receipient's secret key.
- *
- * Note: the keypair of the recipient is required here, both public and secret key.
- * This is because during encryption the recipient's public key is used to generate
- * the nonce. The throwaway public key generated by the sender is stored in the first
- * `crypto_box_PUBLICKEYBYTE`'s of the ciphertext.
- */
- export function crypto_box_seal_open(message: Buffer, ciphertext: Buffer, publicKey: Buffer, secretKey: Buffer): void
-
- /**
- * Encrypt a message.
- *
- * * `ciphertext` should be a buffer with length `message.length`.
- * * `mac` should be a buffer with length `crypto_secretbox_MACBYTES`.
- * * `message` should be a buffer of any length.
- * * `nonce` should be a buffer with length `crypto_secretbox_NONCEBYTES`.
- * * `secretKey` should be a secret key with legnth `crypto_secretbox_KEYBYTES`.
- *
- * The encrypted message will be stored in `ciphertext` and the authentification code will be stored in `mac`.
- */
- export function crypto_secretbox_detached(
- ciphertext: Buffer,
- mac: Buffer,
- message: Buffer,
- nonce: Buffer,
- secretKey: Buffer
- ): void
-
- /**
- * Same as `crypto_secretbox_detached` except it encodes the mac in the message.
- *
- * * `ciphertext` should be a buffer with length `message.length + crypto_secretbox_MACBYTES`.
- * * `message` should be a buffer of any length.
- * * `nonce` should be a buffer with length `crypto_secretbox_NONCEBYTES`.
- * * `secretKey` should be a secret key with length `crypto_secretbox_KEYBYTES`.
- */
- export function crypto_secretbox_easy(ciphertext: Buffer, message: Buffer, nonce: Buffer, secretKey: Buffer): void
-
- /**
- * Decrypt a message.
- *
- * * `message` should be a buffer with length `ciphertext.length`.
- * * `mac` should be a buffer with length `crypto_secretbox_MACBYTES`.
- * * `ciphertext` should be a buffer of any length.
- * * `nonce` should be a buffer with length `crypto_secretbox_NONCEBYTES`.
- * * `secretKey` should be a secret key.
- *
- * Returns `true` if the message could be decrypted. Otherwise `false`.
- *
- * The decrypted message will be stored in `message`.
- */
- export function crypto_secretbox_open_detached(
- message: Buffer,
- ciphertext: Buffer,
- mac: Buffer,
- nonce: Buffer,
- secretKey: Buffer
- ): boolean
-
- /**
- * Decrypt a message encoded with the easy method.
- *
- * * `message` should be a buffer with length `ciphertext.length - crypto_secretbox_MACBYTES`.
- * * `ciphertext` should be a buffer with length at least `crypto_secretbox_MACBYTES`.
- * * `nonce` should be a buffer with length `crypto_secretbox_NONCEBYTES`.
- * * `secretKey` should be a secret key.
- *
- * Returns `true` if the message could be decrypted. Otherwise `false`.
- *
- * The decrypted message will be stored in `message`.
- */
- export function crypto_secretbox_open_easy(
- message: Buffer,
- ciphertext: Buffer,
- nonce: Buffer,
- secretKey: Buffer
- ): boolean
-
- /**
- * Generate a new encryption key.
- *
- * * `key` should be a buffer of length `crypto_aead_xchacha20poly1305_ietf_KEYBYTES`.
- *
- * The generated key is stored in `key`.
- */
- export function crypto_aead_xchacha20poly1305_ietf_keygen(key: Buffer): void
-
- /**
- * Encrypt a message with (`npub`, `key`) and optional additional data `ad`.
- *
- * * `ciphertext` should be a `Buffer` of size `message.length + crypto_aead_xchacha20poly1305_ietf_ABYTES`.
- * * `message` should be a `Buffer`.
- * * `ad` is optional and should be `null` or `Buffer`. Included in the computation
- * of authentication tag appended to the message.
- * * `nullValue` is in the position of the unused `nsec` argument. This should always be `null`.
- * * `npub` should be `Buffer` of length `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES`.
- * * `key` should be a `Buffer` of length `crypto_aead_xchacha20poly1305_ietf_KEYBYTES`.
- *
- * Returns how many bytes were written to `ciphertext`. Note that in-place
- * encryption is possible.
- */
- export function crypto_aead_xchacha20poly1305_ietf_encrypt(
- ciphertext: Buffer,
- message: Buffer,
- ad: Buffer | null,
- nullValue: null,
- npub: Buffer,
- key: Buffer
- ): void
-
- /**
- * Decrypt a message with (`npub`, `key`) and optional additional data `ad`.
- *
- * * `message` should be a `Buffer` of size
- * `ciphertext.length - crypto_aead_xchacha20poly1305_ietf_ABYTES`.
- * * `nullValue` is in the position of the unused `nsec` argument. This should always be
- * `null`.
- * * `ciphertext` should be a `Buffer`.
- * * `ad` is optional and should be `null` or `Buffer`. Included in the computation
- * of authentication tag appended to the message.
- * * `npub` should be `Buffer` of length `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES`.
- * * `key` should be a `Buffer` of length `crypto_aead_xchacha20poly1305_ietf_KEYBYTES`.
- *
- * Returns how many bytes were written to `message`. Note that in-place
- * encryption is possible.
- */
- export function crypto_aead_xchacha20poly1305_ietf_decrypt(
- message: Buffer,
- nullValue: null,
- ciphertext: Buffer,
- ad: Buffer | null,
- npub: Buffer,
- key: Buffer
- ): void
-
- /**
- * Encrypt a message with (`npub`, `key`) and optional additional data `ad`.
- *
- * * `ciphertext` should be a `Buffer` of size `message.length`.
- * * `mac` should be `Buffer` of size `crypto_aead_xchacha20poly1305_ietf_ABYTES`.
- * * `message` should be a `Buffer`.
- * * `ad` is optional and should be `null` or `Buffer`. Included in the computation
- * of authentication tag appended to the message.
- * * `nullValue` is in the position of the unused `nsec` argument. This should always be `null`.
- * * `npub` should be `Buffer` of length `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES`.
- * * `key` should be a `Buffer` of length `crypto_aead_xchacha20poly1305_ietf_KEYBYTES`.
- *
- * Returns how many bytes were written to `mac`. Note that in-place
- * encryption is possible.
- */
- export function crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
- ciphertext: Buffer,
- mac: Buffer,
- message: Buffer,
- ad: Buffer | null,
- nullValue: null,
- npub: Buffer,
- key: Buffer
- ): void
-
- /**
- * Decrypt a message with (`npub`, `key`) and optional additional data `ad`.
- *
- * * `message` should be a `Buffer` of size `ciphertext.length`.
- * * `nullValue` is in the position of the unused `nsec` argument. This should always be `null`.
- * * `ciphertext` should be a `Buffer`.
- * * `mac` should be `Buffer` of size `crypto_aead_xchacha20poly1305_ietf_ABYTES`.
- * * `ad` is optional and should be `null` or `Buffer`. Included in the computation
- * of authentication tag appended to the message.
- * * `npub` should be `Buffer` of length `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES`.
- * * `key` should be a `Buffer` of length `crypto_aead_xchacha20poly1305_ietf_KEYBYTES`.
- *
- * Returns nothing, but will throw on in case the MAC cannot be authenticated. Note
- * that in-place encryption is possible.
- */
- export function crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
- message: Buffer,
- nullValue: null,
- ciphertext: Buffer,
- mac: Buffer,
- ad: Buffer | null,
- npub: Buffer,
- key: Buffer
- ): void
-
- /**
- * Generate random data based on a nonce and key into the ciphertext.
- *
- * * `ciphertext` should be a buffer of any size.
- * * `nonce` should be a buffer with length `crypto_stream_NONCEBYTES`.
- * * `key` should be a secret key with length `crypto_stream_KEYBYTES`.
- *
- * The generated data is stored in `ciphertext`.
- */
- export function crypto_stream(ciphertext: Buffer, nonce: Buffer, key: Buffer): void
-
- /**
- * Encrypt, but *not* authenticate, a message based on a nonce and key
- *
- * * `ciphertext` should be a buffer with length `message.length`.
- * * `message` should be a buffer of any size.
- * * `nonce` should be a buffer with length `crypto_stream_NONCEBYTES`.
- * * `key` should be a secret key with length `crypto_stream_KEYBYTES`.
- *
- * The encrypted data is stored in `ciphertext`. To decrypt, swap `ciphertext` and `message`.
- * Also supports in-place encryption where you use the same buffer as `ciphertext` and `message`.
- *
- * Encryption defaults to XSalsa20, use `crypto_stream_chacha20_xor` if you want
- * to encrypt/decrypt with ChaCha20 instead.
- *
- */
- export function crypto_stream_xor(ciphertext: Buffer, message: Buffer, nonce: Buffer, key: Buffer): void
-
- /**
- * Encrypt, but *not* authenticate, a message based on a nonce and key
- *
- * * `ciphertext` should be a buffer with length `message.length`.
- * * `message` should be a buffer of any size.
- * * `nonce` should be a buffer with length `crypto_stream_NONCEBYTES`.
- * * `key` should be a secret key with length `crypto_stream_KEYBYTES`.
- *
- * The encrypted data is stored in `ciphertext`. To decrypt, swap `ciphertext` and `message`.
- * Also supports in-place encryption where you use the same buffer as `ciphertext` and `message`.
- */
- export function crypto_stream_chacha20_xor(ciphertext: Buffer, message: Buffer, nonce: Buffer, key: Buffer): void
-
- /**
- * A streaming instance to the `crypto_stream_xor` api. Pass a nonce and key in the constructor.
- *
- * Encryption defaults to XSalsa20, use `crypto_stream_chacha20_xor_instance` if
- * you want to encrypt/decrypt with ChaCha20 instead.
- */
- export function crypto_stream_xor_instance(nonce: Buffer, key: Buffer): CryptoStreamChacha20XorWrap
-
- /**
- *
- * A streaming instance to the `crypto_stream_xor` api. Pass a nonce and key in the constructor.
- */
- export function crypto_stream_chacha20_xor_instance(nonce: Buffer, key: Buffer): CryptoStreamChacha20XorWrap
-
- /**
- * Create an authentication token.
- *
- * * `output` should be a buffer of length `crypto_auth_BYTES`.
- * * `input` should be a buffer of any size.
- * * `key` should be a buffer of lenght `crypto_auth_KEYBYTES`.
- *
- * The generated token is stored in `output`.
- */
- export function crypto_auth(output: Buffer, input: Buffer, key: Buffer): void
-
- /**
- * Verify a token.
- *
- * * `output` should be a buffer of length `crypto_auth_BYTES`.
- * * `input` should be a buffer of any size.
- * * `key` should be a buffer of lenght `crypto_auth_KEYBYTES`.
- *
- * Returns `true` if the token could be verified. Otherwise `false`.
- *
- */
- export function crypto_auth_verify(output: Buffer, input: Buffer, key: Buffer): boolean
-
- /**
- * Generate a new encryption key.
- *
- * * `key` should be a buffer of length `crypto_secretstream_xchacha20poly1305_KEYBYTES`.
- *
- * The generated key is stored in `key`.
- * function crypto_secretstream_xchacha20poly1305_keygen(key)
- *
- * Create a new stream state. Returns an opaque object used in the next methods.
- */
- export function crypto_secretstream_xchacha20poly1305_state_new(): Xchacha20poly1305State
-
- /**
- * Initialise `state` from the writer side with message `header` and
- * encryption key `key`. The header must be sent or stored with the stream.
- * The key must be exchanged securely with the receiving / reading side.
- *
- * * `state` should be an opaque state object.
- * * `header` should be a buffer of size `crypto_secretstream_xchacha20poly1305_HEADERBYTES`.
- * * `key` should be a buffer of length `crypto_secretstream_xchacha20poly1305_KEYBYTES`.
- */
- export function crypto_secretstream_xchacha20poly1305_init_push(
- state: Xchacha20poly1305State,
- header: Buffer,
- key: Buffer
- ): void
-
- /**
- * Encrypt a message with a certain tag and optional additional data `ad`.
- *
- * * `state` should be an opaque state object.
- * * `ciphertext` should be a buffer of size `message.length + crypto_secretstream_xchacha20poly1305_ABYTES`.
- * * `message` should be a buffer.
- * * `ad` is optional and should be `null` or `Buffer`. Included in the computation
- * of authentication tag appended to the message.
- * * `tag` should be `Buffer` of length `crypto_secretstream_xchacha20poly1305_TAGBYTES`
- *
- * Note that `tag` should be one of the `crypto_secretstream_xchacha20poly1305_TAG_*` constants.
- * Returns number of encrypted bytes written to `ciphertext`.
- */
- export function crypto_secretstream_xchacha20poly1305_push(
- state: Xchacha20poly1305State,
- ciphertext: Buffer,
- message: Buffer,
- ad: Buffer | null,
- tag: Buffer
- ): void
-
- /**
- * Initialise `state` from the reader side with message `header` and
- * encryption key `key`. The header must be retrieved from somewhere.
- * The key must be exchanged securely with the sending / writing side.
- *
- * * `state` should be an opaque state object.
- * * `header` should be a buffer of size `crypto_secretstream_xchacha20poly1305_HEADERBYTES`.
- * * `key` should be a buffer of length `crypto_secretstream_xchacha20poly1305_KEYBYTES`.
- */
- export function crypto_secretstream_xchacha20poly1305_init_pull(
- state: Xchacha20poly1305State,
- header: Buffer,
- key: Buffer
- ): void
-
- /**
- * Decrypt a message with optional additional data `ad`, and write message tag to
- * `tag`. Make sure to check this!
- *
- * * `state` should be an opaque state object.
- * * `message` should be a buffer of size `ciphertext.length - crypto_secretstream_xchacha20poly1305_ABYTES`.
- * * `tag` should be a buffer of `crypto_secretstream_xchacha20poly1305_TAGBYTES`.
- * * `ad` is optional and should be `null` or `Buffer`. Included in the computation
- * of the authentication tag appended to the message.
- *
- * Note that `tag` should be one of the `crypto_secretstream_xchacha20poly1305_TAG_*` constants.
- * Returns number of decrypted bytes written to `message`.
- */
- export function crypto_secretstream_xchacha20poly1305_pull(
- state: Xchacha20poly1305State,
- message: Buffer,
- tag: Buffer,
- ciphertext: Buffer,
- ad: Buffer | null
- ): void
-
- /**
- * Rekey the opaque `state` object.
- */
- export function crypto_secretstream_xchacha20poly1305_rekey(state: Xchacha20poly1305State): void
-
- /**
- * Create a authentication token based on a onetime key.
- *
- * * `output` should be a buffer of length `crypto_onetimauth_BYTES`.
- * * `input` should be a buffer of any size.
- * * `key` should be a buffer of length `crypto_onetimeauth_KEYBYTES`.
- *
- * The generated token is stored in `output`.
- */
- export function crypto_onetimeauth(output: Buffer, input: Buffer, key: Buffer): void
-
- /**
- * Verify a token.
- *
- * * `output` should be a buffer of length `crypto_onetimeauth_BYTES`.
- * * `input` should be a buffer of any size.
- * * `key` should be a buffer of lenght `crypto_onetimeauth_KEYBYTES`.
- *
- * Returns `true` if the token could be verified. Otherwise `false`.
- */
- export function crypto_onetimeauth_verify(output: Buffer, input: Buffer, key: Buffer): boolean
-
- /**
- * Create an instance that create a token from a onetime key and a stream of input data.
- *
- * * `key` should be a buffer of length `crypto_onetimeauth_KEYBYTES`.
- */
- export function crypto_onetimeauth_instance(key: Buffer): CryptoOneTimeAuthWrap
-
- /**
- * Create a password hash.
- *
- * * `output` should be a buffer with length within `crypto_pwhash_BYTES_MIN` - `crypto_pwhash_BYTES_MAX`.
- * * `password` should be a buffer of any size.
- * * `salt` should be a buffer with length `crypto_pwhash_SALTBYTES`.
- * * `opslimit` should a be number containing your ops limit setting in the range `crypto_pwhash_OPSLIMIT_MIN` - `crypto_pwhash_OPSLIMIT_MAX`.
- * * `memlimit` should a be number containing your mem limit setting in the range `crypto_pwhash_MEMLIMIT_MIN` - `crypto_pwhash_OPSLIMIT_MAX`.
- * * `algorithm` should be a number specifying the algorithm you want to use.
- *
- * Available default ops and mem limits are
- *
- * * `crypto_pwhash_OPSLIMIT_INTERACTIVE`
- * * `crypto_pwhash_OPSLIMIT_MODERATE`
- * * `crypto_pwhash_OPSLIMIT_SENSITIVE`
- * * `crypto_pwhash_MEMLIMIT_INTERACTIVE`
- * * `crypto_pwhash_MEMLIMIT_MODERATE`
- * * `crypto_pwhash_MEMLIMIT_SENSITIVE`
- *
- * The available algorithms are
- *
- * * `crypto_pwhash_ALG_DEFAULT`
- * * `crypto_pwhash_ALG_ARGON2ID13`
- * * `crypto_pwhash_ALG_ARGON2I13`
- *
- * The generated hash will be stored in `output` and the entire `output` buffer will be used.
- */
- export function crypto_pwhash(
- output: Buffer,
- password: Buffer,
- salt: Buffer,
- opslimit: number,
- memlimit: number,
- algorithm: number
- ): void
-
- /**
- * Create a password hash with a random salt.
- *
- * * `output` should be a buffer with length `crypto_pwhash_STRBYTES`.
- * * `password` should be a buffer of any size.
- * * `opslimit` should a be number containing your ops limit setting in the range `crypto_pwhash_OPSLIMIT_MIN` - `crypto_pwhash_OPSLIMIT_MAX`.
- * * `memlimit` should a be number containing your mem limit setting in the range `crypto_pwhash_MEMLIMIT_MIN` - `crypto_pwhash_OPSLIMIT_MAX`.
- *
- * The generated hash, settings, salt, version and algorithm will be stored in `output` and the entire `output` buffer will be used.
- */
- export function crypto_pwhash_str(output: Buffer, password: Buffer, opslimit: number, memlimit: number): void
-
- /**
- * Verify a password hash generated with the above method.
- *
- * * `str` should be a buffer with length `crypto_pwhash_STRBYTES`.
- * * `password` should be a buffer of any size.
- *
- * Returns `true` if the hash could be verified with the settings contained in `str`. Otherwise `false`.
- */
- export function crypto_pwhash_str_verify(str: Buffer, password: Buffer): boolean
-
- /**
- * Check if a password hash needs rehash, either because the default algorithm
- * changed, opslimit or memlimit increased or because the hash is malformed.
- *
- * * `hash` should be a buffer with length `crypto_pwhash_STRBYTES`.
- * * `opslimit` should a be number containing your ops limit setting in the range `crypto_pwhash_OPSLIMIT_MIN` - `crypto_pwhash_OPSLIMIT_MAX`.
- * * `memlimit` should a be number containing your mem limit setting in the range `crypto_pwhash_MEMLIMIT_MIN` - `crypto_pwhash_OPSLIMIT_MAX`.
- *
- * Returns `true` if the hash should be rehashed the settings contained in `str`.
- * Otherwise `false` if it is still good.
- */
- export function crypto_pwhash_str_needs_rehash(hash: Buffer, opslimit: number, memlimit: number): boolean
-
- /**
- * Just like `crypto_pwhash` but will run password hashing on a seperate worker so it will not block the event loop. `callback(err)` will receive any errors from the hashing but all argument
- * errors will `throw`. The resulting hash is written to `output`. This function also supports [`async_hook`s](https://nodejs.org/dist/latest/docs/api/async_hooks.html) as the type
- * `sodium-native:crypto_pwhash_async`
- */
- export function crypto_pwhash_async(
- output: Buffer,
- password: Buffer,
- salt: Buffer,
- opslimit: number,
- memlimit: number,
- algorithm: number,
- callback: (err: Error | null) => void
- ): void
-
- /**
- * Just like `crypto_pwhash_str` but will run password hashing on a seperate worker so it will not block the event loop. `callback(err)` will receive any errors from the hashing but all argument
- * errors will `throw`. The resulting hash with parameters is written to `output`. This function also supports [`async_hook`s](https://nodejs.org/dist/latest/docs/api/async_hooks.html) as the type
- * `sodium-native:crypto_pwhash_str_async`
- */
- export function crypto_pwhash_str_async(
- output: Buffer,
- password: Buffer,
- opslimit: number,
- memlimit: number,
- callback: (err: Error | null) => void
- ): void
-
- /**
- * Just like `crypto_pwhash_str_verify` but will run password hashing on a seperate worker so it will not block the event loop. `callback(err, bool)` will receive any errors from the hashing but
- * all argument errors will `throw`. If the verification succeeds `bool` is `true`, otherwise `false`. Due to an issue with libsodium `err` is currently never set. This function also supports
- * [`async_hook`s](https://nodejs.org/dist/latest/docs/api/async_hooks.html) as the type `sodium-native:crypto_pwhash_str_verify_async`
- */
- export function crypto_pwhash_str_verify_async(
- str: Buffer,
- password: Buffer,
- callback: (err: Error | null, bool: boolean) => void
- ): void
-
- /**
- * Create a key exchange key pair.
- *
- * * `publicKey` should be a buffer of length `crypto_kx_PUBLICKEYBYTES`.
- * * `secretKey` should be a buffer of length `crypto_kx_SECRETKEYBYTES`.
- */
- export function crypto_kx_keypair(publicKey: Buffer, secretKey: Buffer): void
-
- /**
- * Create a key exchange key pair based on a seed.
- *
- * * `publicKey` should be a buffer of length `crypto_kx_PUBLICKEYBYTES`.
- * * `secretKey` should be a buffer of length `crypto_kx_SECRETKEYBYTES`.
- * * `seed` should be a buffer of length `crypto_kx_SEEDBYTES`
- */
- export function crypto_kx_seed_keypair(publicKey: Buffer, secretKey: Buffer, seed: Buffer): void
-
- /**
- * Generate a session receive and transmission key for a client.
- * The public / secret keys should be generated using the key pair method above.
- *
- * * `rx` should be a buffer of length `crypto_kx_SESSIONKEYBYTES` or `null`.
- * * `tx` should be a buffer of length `crypto_kx_SESSIONKEYBYTES` or `null`.
- *
- * You should use the `rx` to decrypt incoming data and `tx` to encrypt outgoing.
- * If you need to make a one-way or half-duplex channel you can give only one of
- * `rx` or `tx`.
- */
- export function crypto_kx_client_session_keys(
- rx: Buffer | null,
- tx: Buffer | null,
- clientPublicKey: Buffer,
- clientSecretKey: Buffer,
- serverPublicKey: Buffer
- ): void
-
- /**
- * Generate a session receive and transmission key for a server.
- * The public / secret keys should be generated using the key pair method above.
- *
- * * `rx` should be a buffer of length `crypto_kx_SESSIONKEYBYTES` or `null`.
- * * `tx` should be a buffer of length `crypto_kx_SESSIONKEYBYTES` or `null`.
- *
- * You should use the `rx` to decrypt incoming data and `tx` to encrypt outgoing.
- * If you need to make a one-way or half-duplex channel you can give only one of
- * `rx` or `tx`.
- */
- export function crypto_kx_server_session_keys(
- rx: Buffer | null,
- tx: Buffer | null,
- serverPublicKey: Buffer,
- serverSecretKey: Buffer,
- clientPublicKey: Buffer
- ): void
-
- /**
- * Create a scalar multiplication public key based on a secret key
- *
- * * `publicKey` should be a buffer of length `crypto_scalarmult_BYTES`.
- * * `secretKey` should be a buffer of length `crypto_scalarmult_SCALARBYTES`.
- *
- * The generated public key is stored in `publicKey`.
- */
- export function crypto_scalarmult_base(publicKey: Buffer, secretKey: Buffer): void
-
- /**
- * Derive a shared secret from a local secret key and a remote public key.
- *
- * * `sharedSecret` shoudl be a buffer of length `crypto_scalarmult_BYTES`.
- * * `secretKey` should be a buffer of length `crypto_scalarmult_SCALARBYTES`.
- * * `remotePublicKey` should be a buffer of length `crypto_scalarmult_BYTES`.
- *
- * The generated shared secret is stored in `sharedSecret`.
- */
- export function crypto_scalarmult(sharedSecret: Buffer, secretKey: Buffer, remotePublicKey: Buffer): void
-
- /**
- * > The crypto_core_ed25519_is_valid_point() function checks that p represents
- * > a point on the edwards25519 curve, in canonical form, on the main subgroup,
- * > and that the point doesn't have a small order.
- *
- * * `p` must be `Buffer` of at least `crypto_core_ed25519_BYTES` bytes
- *
- * Returns `true` or `false`
- */
- export function crypto_core_ed25519_is_valid_point(p: Buffer): boolean
-
- /**
- * Maps a `crypto_core_ed25519_UNIFORMBYTES` bytes vector (usually the output of
- * a hash function) to a a valid curve point and stores its compressed
- * representation in `p`.
- *
- * The point is guaranteed to be on the main subgroup.
- *
- * * `p` must be `Buffer` of at least `crypto_core_ed25519_BYTES` bytes
- * * `r` must be `Buffer` of at least `crypto_core_ed25519_UNIFORMBYTES` bytes
- */
- export function crypto_core_ed25519_from_uniform(p: Buffer, r: Buffer): void
-
- /**
- * Multiply point `p` by scalar `n` and store its compressed representation in `q`.
- *
- * * `q` must be `Buffer` of at least `crypto_scalarmult_ed25519_BYTES` bytes
- * * `n` must be `Buffer` of at least `crypto_scalarmult_ed25519_SCALARBYTES` bytes
- * * `p` must be `Buffer` of at least `crypto_scalarmult_ed25519_BYTES` bytes
- *
- * Note this function will throw if `n` is zero or `p` is an invalid curve point.
- */
- export function crypto_scalarmult_ed25519(q: Buffer, n: Buffer, p: Buffer): void
-
- /**
- * Multiply the basepoint by scalar `n` and store its compressed representation in
- * `q`. Note that `n` will be clamped.
- *
- * * `q` must be `Buffer` of at least `crypto_scalarmult_ed25519_BYTES` bytes
- * * `n` must be `Buffer` of at least `crypto_scalarmult_ed25519_SCALARBYTES` bytes
- *
- * Note this function will throw if `n` is zero
- */
- export function crypto_scalarmult_ed25519_base(q: Buffer, n: Buffer): void
-
- /**
- * Multiply point `p` by scalar `n` and store its compressed representation in `q`.
- * This version does not clamp.
- *
- * * `q` must be `Buffer` of at least `crypto_scalarmult_ed25519_BYTES` bytes
- * * `n` must be `Buffer` of at least `crypto_scalarmult_ed25519_SCALARBYTES` bytes
- * * `p` must be `Buffer` of at least `crypto_scalarmult_ed25519_BYTES` bytes
- *
- * Note this function will throw if `n` is zero or `p` is an invalid curve point.
- */
- export function crypto_scalarmult_ed25519_noclamp(q: Buffer, n: Buffer, p: Buffer): void
-
- /**
- * Multiply the basepoint by scalar `n` and store its compressed representation in
- * `q`. This version does not clamp.
- *
- * * `q` must be `Buffer` of at least `crypto_scalarmult_ed25519_BYTES` bytes
- * * `n` must be `Buffer` of at least `crypto_scalarmult_ed25519_SCALARBYTES` bytes
- *
- * Note this function will throw if `n` is zero
- */
- export function crypto_scalarmult_ed25519_base_noclamp(q: Buffer, n: Buffer): void
-
- /**
- * Add point `q` to `p`, storing the result to `r`.
- *
- * * `r` must be `Buffer` of at least `crypto_core_ed25519_BYTES` bytes
- * * `p` must be `Buffer` of at least `crypto_core_ed25519_BYTES` bytes
- * * `q` must be `Buffer` of at least `crypto_core_ed25519_BYTES` bytes
- *
- * Will throw if `p`, `q` are not valid curve points
- */
- export function crypto_core_ed25519_add(r: Buffer, p: Buffer, q: Buffer): void
-
- /**
- * Subtract point `q` to `p`, storing the result to `r`.
- *
- * * `r` must be `Buffer` of at least `crypto_core_ed25519_BYTES` bytes
- * * `p` must be `Buffer` of at least `crypto_core_ed25519_BYTES` bytes
- * * `q` must be `Buffer` of at least `crypto_core_ed25519_BYTES` bytes
- *
- * Will throw if `p`, `q` are not valid curve points
- */
- export function crypto_core_ed25519_sub(r: Buffer, p: Buffer, q: Buffer): void
-
- /**
- * Generate random point, storing it in `r`.
- *
- * * `r` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- */
- export function crypto_core_ed25519_scalar_random(r: Buffer): void
-
- /**
- * Reduce `s mod L`, storing it in `r`.
- *
- * * `r` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- * * `s` must be `Buffer` of at least `crypto_core_ed25519_NONREDUCEDSCALARBYTES` bytes
- */
- export function crypto_core_ed25519_scalar_reduce(r: Buffer, s: Buffer): void
-
- /**
- * Find `recip` such that `s * recip = 1 (mod L)`, storing it in `recip`.
- *
- * * `recip` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- * * `s` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- */
- export function crypto_core_ed25519_scalar_invert(recip: Buffer, s: Buffer): void
-
- /**
- * Find `neg` such that `s + neg = 0 (mod L)`, storing it in `recip`.
- *
- * * `recip` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- * * `s` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- */
- export function crypto_core_ed25519_scalar_negate(neg: Buffer, s: Buffer): void
-
- /**
- * Find `comp` such that `s + comp = 1 (mod L)`, storing it in `recip`.
- *
- * * `comp` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- * * `s` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- */
- export function crypto_core_ed25519_scalar_complement(comp: Buffer, s: Buffer): void
-
- /**
- * Add `x` and `y` such that `x + y = z (mod L)`, storing it in `z`.
- *
- * * `x` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- * * `y` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- * * `z` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- */
- export function crypto_core_ed25519_scalar_add(z: Buffer, x: Buffer, y: Buffer): void
-
- /**
- * Subtract `x` and `y` such that `x - y = z (mod L)`, storing it in `z`.
- *
- * * `x` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- * * `y` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- * * `z` must be `Buffer` of at least `crypto_core_ed25519_SCALARBYTES` bytes
- */
- export function crypto_core_ed25519_scalar_sub(z: Buffer, x: Buffer, y: Buffer): void
-
- /**
- * Hash a value to a short hash based on a key.
- *
- * * `output` should be a buffer of length `crypto_shorthash_BYTES`.
- * * `input` should be a buffer of any size.
- * * `key` should be a buffer of length `crypto_shorthash_KEYBYTES`.
- *
- * The generated short hash is stored in `output`.
- */
- export function crypto_shorthash(output: Buffer, input: Buffer, key: Buffer): void
-
- /**
- * Generate a new master key.
- *
- * * `key` should be a buffer of length `crypto_kdf_KEYBYTES`
- */
- export function crypto_kdf_keygen(key: Buffer): void
-
- /**
- * Derive a new key from a master key.
- *
- * * `subkey` should be a buffer between `crypto_kdf_BYTES_MIN` and `crypto_kdf_BYTES_MAX`.
- * * `subkeyId` should be an integer.
- * * `context` should be a buffer of length `crypto_kdf_CONTEXTBYTES`
- * * `key` should by a buffer of length `crypto_kdf_KEYBYTES`
- */
- export function crypto_kdf_derive_from_key(subkey: Buffer, subkeyId: number, context: Buffer, key: Buffer): void
-
- /**
- * Hash a value to a short hash based on a key.
- *
- * * `output` should be a buffer of length `crypto_hash_sha256_BYTES`.
- * * `input` should be a buffer of any size.
- *
- * The generated short hash is stored in `output`.
- */
- export function crypto_hash_sha256(output: Buffer, input: Buffer): void
-
- /**
- * Create an instance that has stream of input data to sha256.
- */
- export function crypto_hash_sha256_instance(): CryptoHashSha256Wrap
-
- /**
- * Hash a value to a short hash based on a key.
- *
- * * `output` should be a buffer of length `crypto_hash_sha512_BYTES`.
- * * `input` should be a buffer of any size.
- *
- * The generated short hash is stored in `output`.
- */
- export function crypto_hash_sha512(output: Buffer, input: Buffer): void
-
- /**
- * Create an instance that has stream of input data to sha512.
- */
- export function crypto_hash_sha512_instance(): CryptoHashSha512Wrap
-
- export interface CryptoHashSha512Wrap {
- /**
- * Update the instance with a new piece of data.
- *
- * * `input` should be a buffer of any size.
- */
- update(input: Buffer): void
-
- /**
- * Finalize the instance.
- *
- * * `output` should be a buffer of length `crypto_hash_sha512_BYTES`.
- *
- * The generated hash is stored in `output`.
- */
- final(output: Buffer): void
- }
-}
diff --git a/test/unit/detachedSignatures.test.ts b/test/unit/detachedSignatures.test.ts
new file mode 100644
index 0000000..8e64d91
--- /dev/null
+++ b/test/unit/detachedSignatures.test.ts
@@ -0,0 +1,214 @@
+import * as crypto from '../../src/index'
+
+describe('Detached Signatures', () => {
+ beforeAll(() => {
+ crypto.init('69fa4195670576c0160d660c3be36556ff8d504725be8a59b5a96509e0c994bc')
+ })
+
+ describe('signDetached and verifyDetached', () => {
+ it('should create and verify a detached signature', () => {
+ const keypair = crypto.generateKeypair()
+ const message = 'Hello, World!'
+ const messageHash = crypto.hash(message)
+
+ // Create detached signature
+ const signature = crypto.signDetached(messageHash, keypair.secretKey)
+
+ // Verify signature is 64 bytes (128 hex chars)
+ expect(signature.length).toBe(128)
+
+ // Verify the signature
+ const isValid = crypto.verifyDetached(messageHash, signature, keypair.publicKey)
+ expect(isValid).toBe(true)
+
+ // Verify with wrong message fails
+ const wrongMessage = crypto.hash('Wrong message')
+ const isInvalid = crypto.verifyDetached(wrongMessage, signature, keypair.publicKey)
+ expect(isInvalid).toBe(false)
+ })
+ })
+
+ describe('signObjDetached and verifyObjDetached', () => {
+ it('should sign and verify objects with detached signatures', () => {
+ const keypair = crypto.generateKeypair()
+ const testObj = {
+ message: 'Test object',
+ value: 42,
+ timestamp: Date.now(),
+ }
+
+ // Sign with detached signature
+ const signedObj = crypto.signObjDetached(testObj, keypair.secretKey, keypair.publicKey)
+
+ // Verify signature is 64 bytes
+ expect(signedObj.sign.sig.length).toBe(128)
+
+ // Verify the signed object
+ const isValid = crypto.verifyObjDetached(signedObj)
+ expect(isValid).toBe(true)
+
+ // Tamper with object and verify it fails
+ signedObj.value = 43
+ const isInvalid = crypto.verifyObjDetached(signedObj)
+ expect(isInvalid).toBe(false)
+ })
+ })
+
+ describe('Backward compatibility', () => {
+ it('should verify both old and new signatures with auto-detection', () => {
+ const keypair = crypto.generateKeypair()
+ const message = 'Test message'
+ const messageHash = crypto.hash(message)
+
+ // Create old-style (non-detached) signature
+ const oldSignature = crypto.sign(messageHash, keypair.secretKey, false)
+ // Old signature should be 96 bytes for 32-byte hash (64 + 32)
+ expect(oldSignature.length).toBe(192)
+
+ // Create new-style (detached) signature
+ const newSignature = crypto.sign(messageHash, keypair.secretKey, true)
+ // New signature should be 64 bytes
+ expect(newSignature.length).toBe(128)
+
+ // Both should verify successfully with verifyObj
+ const testObj1 = { data: 'test' }
+ const testObj2 = { data: 'test' }
+
+ // Sign with old style
+ const signedObj1 = crypto.signObj(testObj1, keypair.secretKey, keypair.publicKey, false)
+ expect(crypto.verifyObj(signedObj1)).toBe(true)
+
+ // Sign with new style
+ const signedObj2 = crypto.signObj(testObj2, keypair.secretKey, keypair.publicKey, true)
+ expect(crypto.verifyObj(signedObj2)).toBe(true)
+ })
+
+ it('should handle mixed signature types correctly', () => {
+ const keypair = crypto.generateKeypair()
+ const testObj = { data: 'test data', id: 123 }
+
+ // Create both types of signatures
+ const objOld = JSON.parse(JSON.stringify(testObj))
+ const objNew = JSON.parse(JSON.stringify(testObj))
+
+ // Sign with old method
+ crypto.signObj(objOld, keypair.secretKey, keypair.publicKey, false)
+
+ // Sign with new method
+ crypto.signObj(objNew, keypair.secretKey, keypair.publicKey, true)
+
+ // Old signature should be longer
+ expect(objOld.sign.sig.length).toBeGreaterThan(objNew.sign.sig.length)
+
+ // Both should verify with verifyObj (auto-detection)
+ expect(crypto.verifyObj(objOld)).toBe(true)
+ expect(crypto.verifyObj(objNew)).toBe(true)
+
+ // New detached verify should work only with detached signature
+ expect(crypto.verifyObjDetached(objNew)).toBe(true)
+ expect(() => crypto.verifyObjDetached(objOld)).toThrow()
+ })
+ })
+
+ describe('Sign function with detached parameter', () => {
+ it('should produce different signature lengths based on detached parameter', () => {
+ const keypair = crypto.generateKeypair()
+ const message = crypto.hash('test')
+
+ // Default (undefined) should now use detached
+ const defaultSig = crypto.sign(message, keypair.secretKey)
+ expect(defaultSig.length).toBe(128) // 64 bytes sig only
+
+ // Explicit false should use non-detached
+ const nonDetachedSig = crypto.sign(message, keypair.secretKey, false)
+ expect(nonDetachedSig.length).toBe(192) // 96 bytes = 64 sig + 32 msg
+
+ // Explicit true should use detached
+ const detachedSig = crypto.sign(message, keypair.secretKey, true)
+ expect(detachedSig.length).toBe(128) // 64 bytes sig only
+ })
+ })
+
+ describe('Default behavior change', () => {
+ it('sign() should default to detached signatures', () => {
+ const keypair = crypto.generateKeypair()
+ const message = crypto.hash('test message')
+
+ // Call without detached parameter
+ const signature = crypto.sign(message, keypair.secretKey)
+
+ // Should produce 64-byte signature
+ expect(signature.length).toBe(128) // 128 hex chars = 64 bytes
+
+ // Should verify with verifyDetached
+ expect(crypto.verifyDetached(message, signature, keypair.publicKey)).toBe(true)
+ })
+
+ it('signObj() should default to detached signatures', () => {
+ const keypair = crypto.generateKeypair()
+ const obj = { data: 'test', value: 123 }
+
+ // Call without detached parameter
+ const signedObj = crypto.signObj(obj, keypair.secretKey, keypair.publicKey)
+
+ // Should produce 64-byte signature
+ expect(signedObj.sign.sig.length).toBe(128)
+
+ // Should verify with both methods due to auto-detection
+ expect(crypto.verifyObj(signedObj)).toBe(true)
+ expect(crypto.verifyObjDetached(signedObj)).toBe(true)
+ })
+ })
+
+ describe('Manual signature conversion', () => {
+ it('should convert non-detached signature to detached by removing excess and verify with verifyObj', () => {
+ const keypair = crypto.generateKeypair()
+ const testObj = {
+ message: 'Test conversion',
+ timestamp: Date.now(),
+ id: 'test-123',
+ }
+
+ // Create a copy for manual signature manipulation
+ const objForManualConversion = JSON.parse(JSON.stringify(testObj))
+
+ // Sign with old method (non-detached) - this includes message + signature
+ const signedObjOld = crypto.signObj(objForManualConversion, keypair.secretKey, keypair.publicKey, false)
+
+ // Verify the old signature works
+ expect(crypto.verifyObj(signedObjOld)).toBe(true)
+
+ // Get the non-detached signature
+ const nonDetachedSig = signedObjOld.sign.sig
+
+ // Non-detached signature should be longer than 128 hex chars (64 bytes)
+ expect(nonDetachedSig.length).toBeGreaterThan(128)
+
+ // Manual conversion: Extract just the signature part (first 128 hex chars = 64 bytes)
+ // In libsodium, non-detached signatures have format: [64-byte signature][original message]
+ const detachedSigFromOld = nonDetachedSig.substring(0, 128)
+
+ // Verify the detached signature is exactly 64 bytes
+ expect(detachedSigFromOld.length).toBe(128)
+
+ // Create a new object with the manually converted detached signature
+ const objWithDetachedSig = {
+ ...testObj,
+ sign: {
+ owner: signedObjOld.sign.owner,
+ sig: detachedSigFromOld,
+ },
+ }
+
+ // This should verify successfully using verifyObj with auto-detection
+ expect(crypto.verifyObj(objWithDetachedSig)).toBe(true)
+
+ // It should also verify with the specific detached verification method
+ expect(crypto.verifyObjDetached(objWithDetachedSig)).toBe(true)
+
+ // For additional verification, let's also test direct signature verification
+ const objHash = crypto.hashObj(objWithDetachedSig, true) // true to remove sign field for hashing
+ expect(crypto.verifyDetached(objHash, detachedSigFromOld, keypair.publicKey)).toBe(true)
+ })
+ })
+})
diff --git a/tsconfig.json b/tsconfig.json
index 03bae60..23e6ba9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -12,6 +12,6 @@
"noImplicitReturns": false,
"typeRoots": ["node_modules/@types"]
},
- "include": ["src/**/*", "src/tests"],
+ "include": ["src/**/*", "src/tests", "sodium-native.d.ts"],
"exclude": ["./node_modules", "build"]
}