@scintilla-network/keys
v1.4.0
Published
Key management and derivation library for Scintilla Network
Downloads
68
Maintainers
Readme
@scintilla-network/keys
Key management and derivation library for Scintilla Network with support for multiple key types, personas, and chains.
Features
- Key Management
- Extended key derivation (BIP32)
- Mnemonic support (BIP39)
- Multiple chain support (BIP44)
- Secure key storage
- Persona Management
- Personal personas
- Shared personas
- Moniker-based derivation
- Watch-only support
- Chain Support
- Bitcoin (BIP44/49/84)
- Ethereum
- Cosmos
- Scintilla
- Message Encryption, Decryption, Signing and Verification
- SignableMessage primitive with signing and encryption methods
- Signer primitive to handle signing and encryption
- Security
- Secure key derivation
- Watch-only mode
- Private key protection
- Zero dependencies beyond Scintilla core
Installation
npm install @scintilla/keysQuick Start
import { SeedKeyring } from '@scintilla-network/keys';
// Create from mnemonic
const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
const keyring = SeedKeyring.fromMnemonic(mnemonic);
// Get chain-specific keyring (scintilla chain)
const chainKeyring = keyring.getChainKeyring();
// Get specific account (account: 0, see bip44)
const accountKeyring = chainKeyring.getAccountKeyring(0);
const addressKeyring = accountKeyring.getAddressKeyring();
const address = addressKeyring.getAddress().toString(); // sct170psr9zhfp9nd9qeyp0mdggxj9m7y6el2ezeq5
// Create shared persona (between two users)
const sharedKeyring = accountKeyring.getSharedPersonaKeyring('sct.alice', 'sct.bob');
import { SignableMessage } from '@scintilla-network/keys';
const message = SignableMessage.fromString('Hello World');
const signer = sharedKeyring.getSigner();
const [signature, publicKey] = message.sign(signer); // sign the message which can be verified with message.verify(signature, publicKey)
const encryptedMessage = message.encrypt(signer); // encrypt the message which can be decrypted with message.decrypt(encryptedMessage, signer)Usage Guide
Seed Management
import { SeedKeyring } from '@scintilla-network/keys';
// From mnemonic
const keyring = SeedKeyring.fromMnemonic(mnemonic);
// From seed
const seedBuffer = Buffer.from('your-seed-hex', 'hex');
const keyring = SeedKeyring.fromSeed(seedBuffer);
// Get chain keyring
const chainKeyring = keyring.getChainKeyring({
chain: 'scintilla', // or 'scintilla', 'ethereum', 'cosmos', 'bitcoin'
purpose: 44, // optional: BIP44/49/84
coinType: 8888 // optional: chain-specific (btc: 0, eth: 60)
});Persona Management
import { SharedPersonaKeyring } from '@scintilla-network/keys';
// Create shared persona
const sharedKeyring = new SharedPersonaKeyring(extendedKey,'alice','bob');
// Get address keyring
const addressKeyring = sharedKeyring.getAddressKeyring(0, { change: 0 });
// Create watch-only persona
const watchOnly = SharedPersonaKeyring.fromExtendedPublicKey(extendedPublicKey,'alice','bob');SignableMessage
Handles message signing and verification:
const message = SignableMessage.fromString("Hello World");
const signer = new Signer(derivableKey);
// Sign message
const [signature, publicKey] = message.sign(signer);
// Verify signature
const isValid = message.verify(signature, publicKey);
// Encrypt message
const encryptedMessage = message.encrypt(signer);
// Decrypt message
const decryptedMessage = message.decrypt(encryptedMessage, signer);Signer
Provides advanced signing capabilities with multiple algorithms:
// Create signer with optional moniker
const signer = new Signer(derivableKey, "myKey");
// Sign with default SECP256K1
const [signature, pubKey] = signer.signMessage("message");
// Sign with BLS
const [blsSignature, blsPubKey] = signer.signMessage("message", Signer.ALGORITHM.BLS);
// Verify signatures
const isValid = signer.verifyMessage(signature, "message", pubKey);
// Encrypt message
const encryptedMessage = signer.encrypt(SignableMessage.fromString('message'));
// Decrypt message
const decryptedMessage = signer.decrypt(encryptedMessage, signer);Utils
The library provides utility functions:
const { bech32, bech32m, escapeHTML, isHexadecimal, sortObjectByKey } = utils;Key Types
SeedKeyring
- Root key management
- Chain derivation
- BIP32/39/44 support
SharedPersonaKeyring
- Shared key derivation
- Moniker-based paths
- Watch-only support
ChainKeyring
- Chain-specific derivation
- Multiple address types
- BIP44/49/84 support
AddressKeyring
- Single address management
- Transaction signing
- Public/private key handling
Security Considerations
Key Storage
- Never store private keys in plaintext
- Consider hardware security modules
- Enable watch-only mode when possible
API Reference
DerivableKey
Constructor Options
privateKey: (string | Buffer) - Either a hex string private key or a seed buffernode: (HDKey) - Optional HD key nodeisMaster: (boolean) - Whether this is a master key for derivation
Methods
derive(path: string): DerivableKey- Derives a child key from the given pathtoAddress(prefix?: string): string- Generates an address with optional prefixgetAccount(accountIndex?: number, coinType?: number): Account- Derives a child account
SignableMessage
Constructor Options
input: (Uint8Array) - The message to be signed
Static Methods
fromHex(hex: string): SignableMessage- Creates SignableMessage from hex stringfromObject(object: object): SignableMessage- Creates SignableMessage from objectfromString(string: string): SignableMessage- Creates SignableMessage from string
Methods
toHex(): string- Converts message to hex formatsign(signer: Signer): [string, string]- Signs message, returns [signature, publicKey]verify(signature: string, publicKey: string): boolean- Verifies signatureencrypt(signer: Signer, algorithm?: CIPHERS, nonce?: Uint8Array): string- Encrypts messagedecrypt(encryptedMessage: string, signer: Signer, algorithm?: CIPHERS): string- Decrypts message
Methods
toHex(): string- Converts message to hex formatsign(signer: Signer): [string, string]- Signs message, returns [signature, publicKey]verify(signature: string, publicKey: string): boolean- Verifies signatureencrypt(signer: Signer, algorithm?: CIPHERS, nonce?: Uint8Array): string- Encrypts messagedecrypt(encryptedMessage: string, signer: Signer, algorithm?: CIPHERS): string- Decrypts message
Signer
Constructor Options
derivableKey: (DerivableKey | string) - Key for signingmoniker: (string | null) - Optional identifiertype: (string) - Signer type, defaults to 'persona.owner'
Methods
signMessage(message: any, algorithm?: ALGORITHM): [string, string]- Signs message with specified algorithmverifyMessage(signature: string, message: any, publicKey: string, algorithm?: ALGORITHM): boolean- Verifies signaturetoAddress(bech32Prefix?: string): string- Generates address from signer's keyencrypt(message: SignableMessage, algorithm?: CIPHERS, nonce?: Uint8Array): string- Encrypts messagedecrypt(encryptedMessage: string, algorithm?: CIPHERS): string- Decrypts message
Utils
base64
import { base64 } from '@scintilla-network/keys/utils';toUint8Array(base64String: string): Uint8Array- Converts base64 string to Uint8Array
base64.toUint8Array('SGVsbG8sIFdvcmxkIQ=='); // Uint8Array([72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33])toHex(base64String: string): string- Converts base64 string to hex string
base64.toHex('SGVsbG8sIFdvcmxkIQ=='); // '48656c6c6f2c20576f726c6421'toString(base64String: string): string- Converts base64 string to string
base64.toString('SGVsbG8sIFdvcmxkIQ=='); // 'Hello, World!'fromUint8Array(bytes: Uint8Array): string- Converts Uint8Array to base64 string
base64.fromUint8Array(new Uint8Array([72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33])); // 'SGVsbG8sIFdvcmxkIQ=='fromHex(hex: string): string- Converts hex string to base64 string
base64.fromHex('48656c6c6f2c20576f726c6421'); // 'SGVsbG8sIFdvcmxkIQ=='fromString(string: string): string- Converts string to base64 string
base64.fromString('Hello, World!'); // 'SGVsbG8sIFdvcmxkIQ=='bech32 / bech32m
import { bech32, bech32m } from '@scintilla-network/keys/utils';encode(prefix: string, words: number[], limit?: number): string- Encodes words to bech32 stringdecode(str: string, limit?: number): {prefix: string, words: number[]}- Decodes bech32 string to wordsdecodeUnsafe(str: string, limit?: number): {prefix: string, words: number[]} | undefined- Decodes bech32 string to words safelytoWords(bytes: number[]): number[]- Converts bytes to wordsfromWords(words: number[]): number[]- Converts words to bytesfromWordsUnsafe(words: number[]): number[] | undefined- Converts words to bytes safely
escapeHTML / unescapeHTML
import { escapeHTML, unescapeHTML } from '@scintilla-network/keys/utils';escapeHTML(str: string): string- Escapes HTML charactersunescapeHTML(str: string): string- Unescapes HTML characters
hex
import { hex } from '@scintilla-network/keys/utils';isHex(hex: string): boolean- Checks if hex string is validtoUint8Array(hex: string): Uint8Array- Converts hex string to Uint8ArrayfromUint8Array(bytes: Uint8Array): string- Converts Uint8Array to hex stringtoHex(bytes: Uint8Array): string- Converts Uint8Array to hex stringtoString(hex: string): string- Converts hex string to string
json
import { json } from '@scintilla-network/keys/utils';stringify(obj: any): string- Stringifies objectparse(str: string, options?: { shouldBigInt?: boolean; shouldUint8Array?: boolean }): any- Parses JSON stringsortObjectByKey(obj: any): any- Sorts object by keysortedJsonByKeyStringify(obj: any): string- Sorts object by key and stringifies objectexcludingStringify(obj: any, fieldsToExclude?: string[]): string- Excludes fields from an object and returns a JSON string
moniker
import { moniker } from '@scintilla-network/keys/utils';validate(moniker: string): boolean- Validates monikerderiveSharedMonikerPath(moniker1: string, moniker2: string, hardened?: boolean): { path: string; moniker1AsNumber: number; moniker2AsNumber: number; truncatedHash: Uint8Array; fullHash: Uint8Array }- Derives shared moniker pathderiveMonikerPath(moniker: string, hardened?: boolean): { path: string; monikerAsNumber: number; checksumAsNumber: number; truncatedHash: Uint8Array; fullHash: Uint8Array }- Derives moniker path
uint8array
import { uint8array } from '@scintilla-network/keys/utils';isUint8Array(input: any): boolean- Checks if input is a Uint8ArraytoHex(bytes: Uint8Array): string- Converts Uint8Array to hex stringfromHex(hex: string): Uint8Array- Converts hex string to Uint8ArrayfromObject(obj: any): Uint8Array- Converts object to Uint8ArraytoObject(bytes: Uint8Array): any- Converts Uint8Array to objectfromString(str: string): Uint8Array- Converts string to Uint8ArraytoString(bytes: Uint8Array): string- Converts Uint8Array to stringtoBigInt(bytes: Uint8Array): bigint- Converts Uint8Array to bigintfromBigInt(bigint: bigint): Uint8Array- Converts bigint to Uint8Arraystringify(bytes: Uint8Array): string- Converts Uint8Array to stringequals(bytes1: Uint8Array, bytes2: Uint8Array): boolean- Checks if two Uint8Arrays are equals
utf8
import { utf8 } from '@scintilla-network/keys/utils';toHex(str: string): string- Converts UTF-8 string to hex stringtoUint8Array(str: string): Uint8Array- Converts UTF-8 string to Uint8ArrayfromHex(hex: string): string- Converts hex string to UTF-8 stringfromUint8Array(uint8Array: Uint8Array): string- Converts Uint8Array to UTF-8 stringisUtf8(input: string | Uint8Array | ArrayBuffer): boolean- Checks if input is a valid UTF-8 string
varbigint
import { varbigint } from '@scintilla-network/keys/utils';0x00-0xFA (0-250): Single byte values
0xFB + 2 bytes: 251-65535 (little-endian)
0xFC + 4 bytes: 65536-4294967295 (little-endian)
0xFD + 8 bytes: 4294967296-18446744073709551615 (little-endian)
0xFE + 16 bytes: 18446744073709551616 to 2^128-1 (little-endian)
0xFF + 32 bytes: Up to 2^256-1 (little-endian)
encodeVarBigInt(num: bigint, format?: 'hex' | 'uint8array'): string | Uint8Array- Encodes bigint to varbigintdecodeVarBigInt(input: Uint8Array | string): { value: bigint; length: number }- Decodes varbigint to bigint and returns the length of the buffer consumed.getEncodingLength(num: bigint): number- Gets the minimum number of bytes needed to encode a given value.canEncode(num: bigint): boolean- Checks if bigint can be encoded
varbigint.encodeVarBigInt(100n); // Uint8Array([100])
varbigint.decodeVarBigInt(new Uint8Array([100])); // { value: 100n, length: 1 }
varbigint.getEncodingLength(100n); // 1
varbigint.canEncode(100n); // truevarint
import { varint } from '@scintilla-network/keys/utils';0x00-0xFC (0-252): Single byte values
0xFD + 2 bytes: 253-65535 (little-endian)
0xFE + 4 bytes: 65536-4294967295 (little-endian)
0xFF + 8 bytes: 4294967296-18446744073709551615 (little-endian)
encodeVarInt(num: number | bigint, format?: 'hex' | 'uint8array'): string | Uint8Array- Encodes number or bigint to varintdecodeVarInt(input: Uint8Array | string): { value: number | bigint; length: number }- Decodes varint to number or bigintgetEncodingLength(num: number | bigint): number- Gets the encoding length of number or bigintcanEncode(num: number | bigint): boolean- Checks if number or bigint can be encoded
varint.encodeVarInt(100); // Uint8Array([100])
varint.decodeVarInt(new Uint8Array([100])); // { value: 100, length: 1 }
varint.getEncodingLength(100); // 1
varint.canEncode(100); // trueRelated Packages
- @scintilla-network/signatures
- @scintilla-network/hashes
- @scintilla-network/mnemonic
- @scintilla-network/ciphers
License
MIT License - see the LICENSE file for details
