km-keybind
v1.2.2
Published
Keybind is a broader secure token platform, and `km-keybind` is a cross-platform package for both JavaScript and TypeScript applications. It turns structured values and files into compact, encrypted, identity-bound tokens and is useful when you want to se
Downloads
37
Maintainers
Readme
Keybind
Keybind is a broader secure token platform, and km-keybind is a cross-platform package for both JavaScript and TypeScript applications. It turns structured values and files into compact, encrypted, identity-bound tokens and is useful when you want to send or store self-contained payloads without keeping server-side state.
Package info
- Current npm version: 1.1.0
- Published package:
km-keybind - Supports both JavaScript and TypeScript usage
License
This project is licensed under the Apache License 2.0. See the LICENSE file in this repository for details.
Repository: https://github.com/kingmon6996/keybind-js
Compatibility
- Works in JavaScript projects with standard ESM imports
- Works in TypeScript projects with type definitions included
- Provides the same API for both environments
What Keybind is for
You can use Keybind when you need to:
- create a compact token from a supported JavaScript value such as an object, array, string, Buffer, tuple-like array, set-like array, or file path
- bind that token to a specific user or application context
- keep the payload encrypted and self-contained
- safely pass the token across systems or store it for later use
Typical use cases include:
- temporary session payloads
- encrypted user profile fragments
- backend-to-backend message transport
- short-lived access tokens with embedded data
- compact state handoff between services
Install
npm install km-keybindThe master key
The master key is the secret value that unlocks and protects the token. It is supplied when you create a Keybind instance:
import { Keybind } from 'km-keybind';
const chain = new Keybind('master-key');In JavaScript, you do not use Python's b'' byte literal syntax. km-keybind accepts either:
- a regular string, which is converted to UTF-8 bytes internally
- a
Buffer, if you want to supply binary key material directly
For example:
const chain = new Keybind('master-key');
// or
const chain = new Keybind(Buffer.from('master-key', 'utf8'));In real projects, use a strong secret instead of a sample string. A good master key should be:
- long enough to be unpredictable
- stored securely
- kept private
- reused consistently for the same application context
How to generate a master key
A simple and safe approach in Node.js is to generate a random 32-byte key:
import { randomBytes } from 'crypto';
import { Keybind } from 'km-keybind';
const masterKey = randomBytes(32);
const chain = new Keybind(masterKey);You can also store it in an environment variable:
import { Keybind } from 'km-keybind';
const masterKey = process.env.KEYBIND_MASTER_KEY;
const chain = new Keybind(masterKey);Why the master key matters
- It is the root secret used to derive the encryption key.
- The same key must be used later when decoding the token.
- If the master key changes, the token cannot be decrypted correctly.
Identities
Keybind also takes two identity values during encoding and decoding:
import { Keybind, DICT } from 'km-keybind';
const chain = new Keybind('master-key');
const token = await chain.encode('user123', 'app', DICT, { hello: 'world' });
await chain.decode('user123', 'app', token);These identities bind the token to a specific context. In practice:
- the first identity is often a user, account, or subject
- the second identity is often an app, service, or environment
This means the token is not only encrypted, but also tied to the identities used when it was created.
Full example
Here is a complete example from start to finish:
import { Keybind, DICT } from 'km-keybind';
const chain = new Keybind('example-master-key');
const payload = {
user: 'alice',
role: 'admin',
permissions: ['read', 'write'],
active: true,
};
const token = await chain.encode('alice', 'dashboard', DICT, payload);
console.log('Token:', token);
const [decoded, decodedType] = await chain.decode('alice', 'dashboard', token);
console.log('Decoded:', decoded);
console.log('Decoded type:', decodedType);What happens in this example
- A Keybind instance is created with a master key.
- A supported payload value is prepared.
- The payload is turned into an encrypted token.
- The token is later decoded back into the original value using the same identities.
If you start a new process or create a new runtime, you can still recover the payload as long as you use the same master key, the same token, and the same two identities. The token now carries the metadata and encrypted data needed for decoding, so it behaves as a self-contained, stateless token.
How the library works internally
Keybind supports file payloads via the FILE payload type. When you encode a file path, the raw file contents are encrypted and later decoded to a saved file path under decoded_files/, preserving the original filename.
import { Keybind, FILE } from 'km-keybind';
const chain = new Keybind('example-master-key');
const token = await chain.encode('alice', 'dashboard', FILE, './summary.txt');
const [filePath, decodedType] = await chain.decode('alice', 'dashboard', token);
console.log('Decoded file saved to:', filePath);
console.log('Decoded type:', decodedType);When you call encode, Keybind performs these steps:
- normalizes the two identities.
- wraps the payload into an internal representation and serializes it into bytes for most value types.
- applies optional compression when it improves size.
- derives an encryption key from the master key and identities.
- encrypts the payload.
- produces a compact token string.
When you call decode, it reverses this process:
- validates the token format.
- re-derives the key using the same master key and identities.
- decrypts the payload.
- reconstructs the original value and returns it together with its payload type.
Note: The token is now self-contained, so decoding can happen later with a new Keybind instance in a different runtime/process as long as the same master key and identities are used.
Supported payload types
Keybind supports the following payload types through the same encode/decode flow:
STRfor stringsINTfor integersFLTfor floating-point numbersBOOLfor booleansNULLfor nullARRfor arraysDICTfor objectsBYTESfor raw byte valuesTUPfor tuple-like arraysSETfor set-like arraysOBJfor arbitrary JavaScript objects via string representationFILEfor files on disk
You can import these constants from km-keybind and pass them as the payload type argument to encode.
import { Keybind, STR, INT, FLT, BOOL, NULL, ARR, DICT, BYTES, TUP, SET, OBJ, FILE } from 'km-keybind';
const chain = new Keybind('demo-master-key');
// Strings
await chain.encode('alice', 'app', STR, 'hello world');
// Integers and floats
await chain.encode('alice', 'app', INT, 42);
await chain.encode('alice', 'app', FLT, 3.14159);
// Booleans and null
await chain.encode('alice', 'app', BOOL, true);
await chain.encode('alice', 'app', NULL, null);
// Arrays and objects
await chain.encode('alice', 'app', ARR, [1, 2, 3]);
await chain.encode('alice', 'app', DICT, { name: 'alice', active: true });
// Byte payloads
await chain.encode('alice', 'app', BYTES, Buffer.from([0x00, 0x01, 0x02]));
// Tuple-like and set-like payloads
await chain.encode('alice', 'app', TUP, ['a', 1, true]);
await chain.encode('alice', 'app', SET, ['red', 'green', 'blue']);
// Arbitrary object payloads
class ExampleConfig {
constructor(retries = 3) {
this.retries = retries;
}
toString() {
return `ExampleConfig(retries=${this.retries})`;
}
}
await chain.encode('alice', 'app', OBJ, new ExampleConfig(5));File payload demo
File payloads are a special case. Pass a path string to encode with FILE and Keybind will encrypt the file contents and later write the decoded bytes back to a file in decoded_files/ using the original filename.
import { Keybind, FILE } from 'km-keybind';
const chain = new Keybind('example-master-key');
const token = await chain.encode('alice', 'app', FILE, './sample.txt');
console.log('Token:', token);
const [outputPath, decodedType] = await chain.decode('alice', 'app', token);
console.log('Decoded file saved to:', outputPath);
console.log('Decoded type:', decodedType);Decoding examples
import { Keybind, DICT, FILE } from 'km-keybind';
const chain = new Keybind('example-master-key');
const payloadToken = await chain.encode('alice', 'app', DICT, { role: 'admin' });
const [decodedPayload, decodedType] = await chain.decode('alice', 'app', payloadToken);
console.log(decodedPayload); // { role: 'admin' }
console.log(decodedType); // DICT
const fileToken = await chain.encode('alice', 'app', FILE, './sample.txt');
const [filePath, fileType] = await chain.decode('alice', 'app', fileToken);
console.log(filePath); // decoded_files/sample.txt
console.log(fileType); // FILE