@optimystic/quereus-plugin-crypto 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/crypto.ts","../src/plugin.ts"],"names":["uint8ArrayFromString","uint8ArrayToString"],"mappings":"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","file":"plugin.js","sourcesContent":["/**\n * Cryptographic Functions for Quereus\n *\n * Idiomatic ES module exports with base64url as default encoding.\n * All functions accept and return base64url strings by default for SQL compatibility.\n */\n\nimport { sha256, sha512 } from '@noble/hashes/sha2';\nimport { blake3 } from '@noble/hashes/blake3';\nimport { concatBytes, utf8ToBytes } from '@noble/hashes/utils';\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport { p256 } from '@noble/curves/nist';\nimport { ed25519 } from '@noble/curves/ed25519';\nimport { hexToBytes, bytesToHex } from '@noble/curves/abstract/utils';\nimport { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays';\n\n// Type definitions\nexport type HashAlgorithm = 'sha256' | 'sha512' | 'blake3';\nexport type CurveType = 'secp256k1' | 'p256' | 'ed25519';\nexport type Encoding = 'base64url' | 'base64' | 'hex' | 'utf8' | 'bytes';\n\n/**\n * Convert input to Uint8Array, handling various encodings\n */\nfunction toBytes(input: string | Uint8Array | null | undefined, encoding: Encoding = 'base64url'): Uint8Array {\n\tif (input === null || input === undefined) {\n\t\treturn new Uint8Array(0);\n\t}\n\n\tif (input instanceof Uint8Array) {\n\t\treturn input;\n\t}\n\n\tif (typeof input === 'string') {\n\t\tswitch (encoding) {\n\t\t\tcase 'base64url':\n\t\t\t\treturn uint8ArrayFromString(input, 'base64url');\n\t\t\tcase 'base64':\n\t\t\t\treturn uint8ArrayFromString(input, 'base64');\n\t\t\tcase 'hex':\n\t\t\t\treturn hexToBytes(input);\n\t\t\tcase 'utf8':\n\t\t\t\treturn utf8ToBytes(input);\n\t\t\tdefault:\n\t\t\t\treturn uint8ArrayFromString(input, 'base64url');\n\t\t}\n\t}\n\n\tthrow new Error('Invalid input type');\n}\n\n/**\n * Convert Uint8Array to string in specified encoding\n */\nfunction fromBytes(bytes: Uint8Array, encoding: Encoding = 'base64url'): string | Uint8Array {\n\tswitch (encoding) {\n\t\tcase 'base64url':\n\t\t\treturn uint8ArrayToString(bytes, 'base64url');\n\t\tcase 'base64':\n\t\t\treturn uint8ArrayToString(bytes, 'base64');\n\t\tcase 'hex':\n\t\t\treturn bytesToHex(bytes);\n\t\tcase 'utf8':\n\t\t\treturn uint8ArrayToString(bytes, 'utf8');\n\t\tcase 'bytes':\n\t\t\treturn bytes;\n\t\tdefault:\n\t\t\treturn uint8ArrayToString(bytes, 'base64url');\n\t}\n}\n\n/**\n * Compute hash digest of input data\n *\n * @param data - Data to hash (base64url string or Uint8Array)\n * @param algorithm - Hash algorithm (default: 'sha256')\n * @param inputEncoding - Encoding of input string (default: 'base64url')\n * @param outputEncoding - Encoding of output (default: 'base64url')\n * @returns Hash digest in specified encoding\n *\n * @example\n * ```typescript\n * // Hash UTF-8 text, output as base64url\n * const hash = digest('hello world', 'sha256', 'utf8');\n *\n * // Hash base64url data with SHA-512\n * const hash2 = digest('SGVsbG8', 'sha512');\n *\n * // Get raw bytes\n * const bytes = digest('data', 'blake3', 'utf8', 'bytes');\n * ```\n */\nexport function digest(\n\tdata: string | Uint8Array,\n\talgorithm: HashAlgorithm = 'sha256',\n\tinputEncoding: Encoding = 'base64url',\n\toutputEncoding: Encoding = 'base64url'\n): string | Uint8Array {\n\tconst bytes = toBytes(data, inputEncoding);\n\n\tlet hashBytes: Uint8Array;\n\tswitch (algorithm) {\n\t\tcase 'sha256':\n\t\t\thashBytes = sha256(bytes);\n\t\t\tbreak;\n\t\tcase 'sha512':\n\t\t\thashBytes = sha512(bytes);\n\t\t\tbreak;\n\t\tcase 'blake3':\n\t\t\thashBytes = blake3(bytes);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported hash algorithm: ${algorithm}`);\n\t}\n\n\treturn fromBytes(hashBytes, outputEncoding);\n}\n\n/**\n * Hash data and return modulo of specified bit length\n * Useful for generating fixed-size hash values (e.g., 16-bit, 32-bit)\n *\n * @param data - Data to hash\n * @param bits - Number of bits for the result (e.g., 16 for 16-bit hash)\n * @param algorithm - Hash algorithm (default: 'sha256')\n * @param inputEncoding - Encoding of input string (default: 'base64url')\n * @returns Integer hash value modulo 2^bits\n *\n * @example\n * ```typescript\n * // Get 16-bit hash (0-65535)\n * const hash16 = hashMod('hello', 16, 'sha256', 'utf8');\n *\n * // Get 32-bit hash\n * const hash32 = hashMod('world', 32, 'sha256', 'utf8');\n * ```\n */\nexport function hashMod(\n\tdata: string | Uint8Array,\n\tbits: number,\n\talgorithm: HashAlgorithm = 'sha256',\n\tinputEncoding: Encoding = 'base64url'\n): number {\n\tif (bits <= 0 || bits > 53) {\n\t\tthrow new Error('Bits must be between 1 and 53 (JavaScript safe integer limit)');\n\t}\n\n\tconst hashBytes = toBytes(digest(data, algorithm, inputEncoding, 'base64url') as string, 'base64url');\n\n\t// Take first 8 bytes and convert to number\n\tconst view = new DataView(hashBytes.buffer, hashBytes.byteOffset, Math.min(8, hashBytes.length));\n\tconst fullHash = view.getBigUint64(0, false); // big-endian\n\n\t// Modulo by 2^bits\n\tconst modulus = BigInt(2) ** BigInt(bits);\n\tconst result = fullHash % modulus;\n\n\treturn Number(result);\n}\n\n/**\n * Sign data with a private key\n *\n * @param data - Data to sign (typically a hash)\n * @param privateKey - Private key (base64url string or Uint8Array)\n * @param curve - Elliptic curve (default: 'secp256k1')\n * @param inputEncoding - Encoding of data input (default: 'base64url')\n * @param keyEncoding - Encoding of private key (default: 'base64url')\n * @param outputEncoding - Encoding of signature output (default: 'base64url')\n * @returns Signature in specified encoding\n *\n * @example\n * ```typescript\n * // Sign a hash with secp256k1\n * const sig = sign(hashData, privateKey);\n *\n * // Sign with Ed25519\n * const sig2 = sign(hashData, privateKey, 'ed25519');\n * ```\n */\nexport function sign(\n\tdata: string | Uint8Array,\n\tprivateKey: string | Uint8Array,\n\tcurve: CurveType = 'secp256k1',\n\tinputEncoding: Encoding = 'base64url',\n\tkeyEncoding: Encoding = 'base64url',\n\toutputEncoding: Encoding = 'base64url'\n): string | Uint8Array {\n\tconst dataBytes = toBytes(data, inputEncoding);\n\tconst keyBytes = toBytes(privateKey, keyEncoding);\n\n\tlet sigBytes: Uint8Array;\n\n\tswitch (curve) {\n\t\tcase 'secp256k1': {\n\t\t\tconst sig = secp256k1.sign(dataBytes, keyBytes, { lowS: true });\n\t\t\tsigBytes = sig.toCompactRawBytes();\n\t\t\tbreak;\n\t\t}\n\t\tcase 'p256': {\n\t\t\tconst sig = p256.sign(dataBytes, keyBytes, { lowS: true });\n\t\t\tsigBytes = sig.toCompactRawBytes();\n\t\t\tbreak;\n\t\t}\n\t\tcase 'ed25519': {\n\t\t\tsigBytes = ed25519.sign(dataBytes, keyBytes);\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported curve: ${curve}`);\n\t}\n\n\treturn fromBytes(sigBytes, outputEncoding);\n}\n\n/**\n * Verify a signature\n *\n * @param data - Data that was signed\n * @param signature - Signature to verify\n * @param publicKey - Public key\n * @param curve - Elliptic curve (default: 'secp256k1')\n * @param inputEncoding - Encoding of data input (default: 'base64url')\n * @param sigEncoding - Encoding of signature (default: 'base64url')\n * @param keyEncoding - Encoding of public key (default: 'base64url')\n * @returns true if signature is valid, false otherwise\n *\n * @example\n * ```typescript\n * // Verify a signature\n * const isValid = verify(hashData, signature, publicKey);\n *\n * // Verify with Ed25519\n * const isValid2 = verify(hashData, signature, publicKey, 'ed25519');\n * ```\n */\nexport function verify(\n\tdata: string | Uint8Array,\n\tsignature: string | Uint8Array,\n\tpublicKey: string | Uint8Array,\n\tcurve: CurveType = 'secp256k1',\n\tinputEncoding: Encoding = 'base64url',\n\tsigEncoding: Encoding = 'base64url',\n\tkeyEncoding: Encoding = 'base64url'\n): boolean {\n\ttry {\n\t\tconst dataBytes = toBytes(data, inputEncoding);\n\t\tconst sigBytes = toBytes(signature, sigEncoding);\n\t\tconst keyBytes = toBytes(publicKey, keyEncoding);\n\n\t\tswitch (curve) {\n\t\t\tcase 'secp256k1': {\n\t\t\t\treturn secp256k1.verify(sigBytes, dataBytes, keyBytes);\n\t\t\t}\n\t\t\tcase 'p256': {\n\t\t\t\treturn p256.verify(sigBytes, dataBytes, keyBytes);\n\t\t\t}\n\t\t\tcase 'ed25519': {\n\t\t\t\treturn ed25519.verify(sigBytes, dataBytes, keyBytes);\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported curve: ${curve}`);\n\t\t}\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Generate cryptographically secure random bytes\n *\n * @param bits - Number of bits to generate (default: 256)\n * @param encoding - Output encoding (default: 'base64url')\n * @returns Random bytes in the specified encoding\n */\nexport function randomBytes(bits: number = 256, encoding: Encoding = 'base64url'): string | Uint8Array {\n\tconst bytes = Math.ceil(bits / 8);\n\tconst randomBytesArray = new Uint8Array(bytes);\n\tcrypto.getRandomValues(randomBytesArray);\n\treturn fromBytes(randomBytesArray, encoding);\n}\n\n/**\n * Generate a random private key\n */\nexport function generatePrivateKey(curve: CurveType = 'secp256k1', encoding: Encoding = 'base64url'): string | Uint8Array {\n\tlet keyBytes: Uint8Array;\n\n\tswitch (curve) {\n\t\tcase 'secp256k1':\n\t\t\tkeyBytes = secp256k1.utils.randomPrivateKey();\n\t\t\tbreak;\n\t\tcase 'p256':\n\t\t\tkeyBytes = p256.utils.randomPrivateKey();\n\t\t\tbreak;\n\t\tcase 'ed25519':\n\t\t\tkeyBytes = ed25519.utils.randomPrivateKey();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported curve: ${curve}`);\n\t}\n\n\treturn fromBytes(keyBytes, encoding);\n}\n\n/**\n * Get public key from private key\n */\nexport function getPublicKey(\n\tprivateKey: string | Uint8Array,\n\tcurve: CurveType = 'secp256k1',\n\tkeyEncoding: Encoding = 'base64url',\n\toutputEncoding: Encoding = 'base64url'\n): string | Uint8Array {\n\tconst keyBytes = toBytes(privateKey, keyEncoding);\n\n\tlet pubBytes: Uint8Array;\n\n\tswitch (curve) {\n\t\tcase 'secp256k1':\n\t\t\tpubBytes = secp256k1.getPublicKey(keyBytes);\n\t\t\tbreak;\n\t\tcase 'p256':\n\t\t\tpubBytes = p256.getPublicKey(keyBytes);\n\t\t\tbreak;\n\t\tcase 'ed25519':\n\t\t\tpubBytes = ed25519.getPublicKey(keyBytes);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported curve: ${curve}`);\n\t}\n\n\treturn fromBytes(pubBytes, outputEncoding);\n}\n\n","/**\n * Quereus Plugin Entry Point for Crypto Functions\n *\n * This module provides the plugin registration following Quereus 0.4.5 format.\n * All metadata is in package.json - no manifest export needed.\n */\n\nimport type { Database, FunctionFlags, SqlValue } from '@quereus/quereus';\nimport { digest, sign, verify, hashMod, randomBytes } from './crypto.js';\n\n/**\n * Plugin registration function\n * This is called by Quereus when the plugin is loaded\n */\nexport default function register(_db: Database, _config: Record<string, SqlValue> = {}) {\n\t// Register crypto functions with Quereus\n\tconst functions = [\n\t\t{\n\t\t\tschema: {\n\t\t\t\tname: 'digest',\n\t\t\t\tnumArgs: -1, // Variable arguments: data, algorithm?, inputEncoding?, outputEncoding?\n\t\t\t\tflags: 1 as FunctionFlags, // UTF8\n\t\t\t\treturnType: { typeClass: 'scalar' as const, sqlType: 'TEXT' },\n\t\t\t\timplementation: (...args: SqlValue[]) => {\n\t\t\t\t\tconst [data, algorithm = 'sha256', inputEncoding = 'base64url', outputEncoding = 'base64url'] = args;\n\t\t\t\t\treturn digest(data as string, algorithm as any, inputEncoding as any, outputEncoding as any);\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tschema: {\n\t\t\t\tname: 'sign',\n\t\t\t\tnumArgs: -1, // Variable arguments: data, privateKey, curve?, inputEncoding?, keyEncoding?, outputEncoding?\n\t\t\t\tflags: 1 as FunctionFlags,\n\t\t\t\treturnType: { typeClass: 'scalar' as const, sqlType: 'TEXT' },\n\t\t\t\timplementation: (...args: SqlValue[]) => {\n\t\t\t\t\tconst [data, privateKey, curve = 'secp256k1', inputEncoding = 'base64url', keyEncoding = 'base64url', outputEncoding = 'base64url'] = args;\n\t\t\t\t\treturn sign(data as string, privateKey as string, curve as any, inputEncoding as any, keyEncoding as any, outputEncoding as any);\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tschema: {\n\t\t\t\tname: 'verify',\n\t\t\t\tnumArgs: -1, // Variable arguments: data, signature, publicKey, curve?, inputEncoding?, sigEncoding?, keyEncoding?\n\t\t\t\tflags: 1 as FunctionFlags,\n\t\t\t\treturnType: { typeClass: 'scalar' as const, sqlType: 'INTEGER' },\n\t\t\t\timplementation: (...args: SqlValue[]) => {\n\t\t\t\t\tconst [data, signature, publicKey, curve = 'secp256k1', inputEncoding = 'base64url', sigEncoding = 'base64url', keyEncoding = 'base64url'] = args;\n\t\t\t\t\tconst result = verify(data as string, signature as string, publicKey as string, curve as any, inputEncoding as any, sigEncoding as any, keyEncoding as any);\n\t\t\t\t\treturn result ? 1 : 0;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tschema: {\n\t\t\t\tname: 'hash_mod',\n\t\t\t\tnumArgs: -1, // Variable arguments: data, bits, algorithm?, inputEncoding?\n\t\t\t\tflags: 1 as FunctionFlags,\n\t\t\t\treturnType: { typeClass: 'scalar' as const, sqlType: 'INTEGER' },\n\t\t\t\timplementation: (...args: SqlValue[]) => {\n\t\t\t\t\tconst [data, bits, algorithm = 'sha256', inputEncoding = 'base64url'] = args;\n\t\t\t\t\treturn hashMod(data as string, bits as number, algorithm as any, inputEncoding as any);\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tschema: {\n\t\t\t\tname: 'random_bytes',\n\t\t\t\tnumArgs: -1, // Variable arguments: bits?, encoding?\n\t\t\t\tflags: 1 as FunctionFlags,\n\t\t\t\treturnType: { typeClass: 'scalar' as const, sqlType: 'TEXT' },\n\t\t\t\timplementation: (...args: SqlValue[]) => {\n\t\t\t\t\tconst [bits = 256, encoding = 'base64url'] = args;\n\t\t\t\t\treturn randomBytes(bits as number, encoding as any);\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t];\n\n\treturn {\n\t\tfunctions,\n\t\tvtables: [],\n\t\tcollations: [],\n\t};\n}\n\n"]}
1
+ {"version":3,"sources":["../src/crypto.ts","../src/plugin.ts"],"names":["uint8ArrayFromString","uint8ArrayToString"],"mappings":"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","file":"plugin.js","sourcesContent":["/**\n * Cryptographic Functions for Quereus\n *\n * Idiomatic ES module exports with base64url as default encoding.\n * All functions accept and return base64url strings by default for SQL compatibility.\n */\n\nimport { sha256, sha512 } from '@noble/hashes/sha2.js';\nimport { blake3 } from '@noble/hashes/blake3.js';\nimport { concatBytes, utf8ToBytes } from '@noble/hashes/utils.js';\nimport { secp256k1 } from '@noble/curves/secp256k1.js';\nimport { p256 } from '@noble/curves/nist.js';\nimport { ed25519 } from '@noble/curves/ed25519.js';\nimport { hexToBytes, bytesToHex } from '@noble/curves/utils.js';\nimport { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays';\n\n// Type definitions\nexport type HashAlgorithm = 'sha256' | 'sha512' | 'blake3';\nexport type CurveType = 'secp256k1' | 'p256' | 'ed25519';\nexport type Encoding = 'base64url' | 'base64' | 'hex' | 'utf8' | 'bytes';\n\n/**\n * Convert input to Uint8Array, handling various encodings\n */\nfunction toBytes(input: string | Uint8Array | null | undefined, encoding: Encoding = 'base64url'): Uint8Array {\n\tif (input === null || input === undefined) {\n\t\treturn new Uint8Array(0);\n\t}\n\n\tif (input instanceof Uint8Array) {\n\t\treturn input;\n\t}\n\n\tif (typeof input === 'string') {\n\t\tswitch (encoding) {\n\t\t\tcase 'base64url':\n\t\t\t\treturn uint8ArrayFromString(input, 'base64url');\n\t\t\tcase 'base64':\n\t\t\t\treturn uint8ArrayFromString(input, 'base64');\n\t\t\tcase 'hex':\n\t\t\t\treturn hexToBytes(input);\n\t\t\tcase 'utf8':\n\t\t\t\treturn utf8ToBytes(input);\n\t\t\tdefault:\n\t\t\t\treturn uint8ArrayFromString(input, 'base64url');\n\t\t}\n\t}\n\n\tthrow new Error('Invalid input type');\n}\n\n/**\n * Convert Uint8Array to string in specified encoding\n */\nfunction fromBytes(bytes: Uint8Array, encoding: Encoding = 'base64url'): string | Uint8Array {\n\tswitch (encoding) {\n\t\tcase 'base64url':\n\t\t\treturn uint8ArrayToString(bytes, 'base64url');\n\t\tcase 'base64':\n\t\t\treturn uint8ArrayToString(bytes, 'base64');\n\t\tcase 'hex':\n\t\t\treturn bytesToHex(bytes);\n\t\tcase 'utf8':\n\t\t\treturn uint8ArrayToString(bytes, 'utf8');\n\t\tcase 'bytes':\n\t\t\treturn bytes;\n\t\tdefault:\n\t\t\treturn uint8ArrayToString(bytes, 'base64url');\n\t}\n}\n\n/**\n * Compute hash digest of input data\n *\n * @param data - Data to hash (base64url string or Uint8Array)\n * @param algorithm - Hash algorithm (default: 'sha256')\n * @param inputEncoding - Encoding of input string (default: 'base64url')\n * @param outputEncoding - Encoding of output (default: 'base64url')\n * @returns Hash digest in specified encoding\n *\n * @example\n * ```typescript\n * // Hash UTF-8 text, output as base64url\n * const hash = digest('hello world', 'sha256', 'utf8');\n *\n * // Hash base64url data with SHA-512\n * const hash2 = digest('SGVsbG8', 'sha512');\n *\n * // Get raw bytes\n * const bytes = digest('data', 'blake3', 'utf8', 'bytes');\n * ```\n */\nexport function digest(\n\tdata: string | Uint8Array,\n\talgorithm: HashAlgorithm = 'sha256',\n\tinputEncoding: Encoding = 'base64url',\n\toutputEncoding: Encoding = 'base64url'\n): string | Uint8Array {\n\tconst bytes = toBytes(data, inputEncoding);\n\n\tlet hashBytes: Uint8Array;\n\tswitch (algorithm) {\n\t\tcase 'sha256':\n\t\t\thashBytes = sha256(bytes);\n\t\t\tbreak;\n\t\tcase 'sha512':\n\t\t\thashBytes = sha512(bytes);\n\t\t\tbreak;\n\t\tcase 'blake3':\n\t\t\thashBytes = blake3(bytes);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported hash algorithm: ${algorithm}`);\n\t}\n\n\treturn fromBytes(hashBytes, outputEncoding);\n}\n\n/**\n * Hash data and return modulo of specified bit length\n * Useful for generating fixed-size hash values (e.g., 16-bit, 32-bit)\n *\n * @param data - Data to hash\n * @param bits - Number of bits for the result (e.g., 16 for 16-bit hash)\n * @param algorithm - Hash algorithm (default: 'sha256')\n * @param inputEncoding - Encoding of input string (default: 'base64url')\n * @returns Integer hash value modulo 2^bits\n *\n * @example\n * ```typescript\n * // Get 16-bit hash (0-65535)\n * const hash16 = hashMod('hello', 16, 'sha256', 'utf8');\n *\n * // Get 32-bit hash\n * const hash32 = hashMod('world', 32, 'sha256', 'utf8');\n * ```\n */\nexport function hashMod(\n\tdata: string | Uint8Array,\n\tbits: number,\n\talgorithm: HashAlgorithm = 'sha256',\n\tinputEncoding: Encoding = 'base64url'\n): number {\n\tif (bits <= 0 || bits > 53) {\n\t\tthrow new Error('Bits must be between 1 and 53 (JavaScript safe integer limit)');\n\t}\n\n\tconst hashBytes = toBytes(digest(data, algorithm, inputEncoding, 'base64url') as string, 'base64url');\n\n\t// Take first 8 bytes and convert to number\n\tconst view = new DataView(hashBytes.buffer, hashBytes.byteOffset, Math.min(8, hashBytes.length));\n\tconst fullHash = view.getBigUint64(0, false); // big-endian\n\n\t// Modulo by 2^bits\n\tconst modulus = BigInt(2) ** BigInt(bits);\n\tconst result = fullHash % modulus;\n\n\treturn Number(result);\n}\n\n/**\n * Sign data with a private key\n *\n * @param data - Data to sign (typically a hash)\n * @param privateKey - Private key (base64url string or Uint8Array)\n * @param curve - Elliptic curve (default: 'secp256k1')\n * @param inputEncoding - Encoding of data input (default: 'base64url')\n * @param keyEncoding - Encoding of private key (default: 'base64url')\n * @param outputEncoding - Encoding of signature output (default: 'base64url')\n * @returns Signature in specified encoding\n *\n * @example\n * ```typescript\n * // Sign a hash with secp256k1\n * const sig = sign(hashData, privateKey);\n *\n * // Sign with Ed25519\n * const sig2 = sign(hashData, privateKey, 'ed25519');\n * ```\n */\nexport function sign(\n\tdata: string | Uint8Array,\n\tprivateKey: string | Uint8Array,\n\tcurve: CurveType = 'secp256k1',\n\tinputEncoding: Encoding = 'base64url',\n\tkeyEncoding: Encoding = 'base64url',\n\toutputEncoding: Encoding = 'base64url'\n): string | Uint8Array {\n\tconst dataBytes = toBytes(data, inputEncoding);\n\tconst keyBytes = toBytes(privateKey, keyEncoding);\n\n\tlet sigBytes: Uint8Array;\n\n\tswitch (curve) {\n\t\tcase 'secp256k1':\n\t\t\tsigBytes = secp256k1.sign(dataBytes, keyBytes, { lowS: true });\n\t\t\tbreak;\n\t\tcase 'p256':\n\t\t\tsigBytes = p256.sign(dataBytes, keyBytes, { lowS: true });\n\t\t\tbreak;\n\t\tcase 'ed25519':\n\t\t\tsigBytes = ed25519.sign(dataBytes, keyBytes);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported curve: ${curve}`);\n\t}\n\n\treturn fromBytes(sigBytes, outputEncoding);\n}\n\n/**\n * Verify a signature\n *\n * @param data - Data that was signed\n * @param signature - Signature to verify\n * @param publicKey - Public key\n * @param curve - Elliptic curve (default: 'secp256k1')\n * @param inputEncoding - Encoding of data input (default: 'base64url')\n * @param sigEncoding - Encoding of signature (default: 'base64url')\n * @param keyEncoding - Encoding of public key (default: 'base64url')\n * @returns true if signature is valid, false otherwise\n *\n * @example\n * ```typescript\n * // Verify a signature\n * const isValid = verify(hashData, signature, publicKey);\n *\n * // Verify with Ed25519\n * const isValid2 = verify(hashData, signature, publicKey, 'ed25519');\n * ```\n */\nexport function verify(\n\tdata: string | Uint8Array,\n\tsignature: string | Uint8Array,\n\tpublicKey: string | Uint8Array,\n\tcurve: CurveType = 'secp256k1',\n\tinputEncoding: Encoding = 'base64url',\n\tsigEncoding: Encoding = 'base64url',\n\tkeyEncoding: Encoding = 'base64url'\n): boolean {\n\ttry {\n\t\tconst dataBytes = toBytes(data, inputEncoding);\n\t\tconst sigBytes = toBytes(signature, sigEncoding);\n\t\tconst keyBytes = toBytes(publicKey, keyEncoding);\n\n\t\tswitch (curve) {\n\t\t\tcase 'secp256k1': {\n\t\t\t\treturn secp256k1.verify(sigBytes, dataBytes, keyBytes);\n\t\t\t}\n\t\t\tcase 'p256': {\n\t\t\t\treturn p256.verify(sigBytes, dataBytes, keyBytes);\n\t\t\t}\n\t\t\tcase 'ed25519': {\n\t\t\t\treturn ed25519.verify(sigBytes, dataBytes, keyBytes);\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported curve: ${curve}`);\n\t\t}\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Generate cryptographically secure random bytes\n *\n * @param bits - Number of bits to generate (default: 256)\n * @param encoding - Output encoding (default: 'base64url')\n * @returns Random bytes in the specified encoding\n */\nexport function randomBytes(bits: number = 256, encoding: Encoding = 'base64url'): string | Uint8Array {\n\tconst bytes = Math.ceil(bits / 8);\n\tconst randomBytesArray = new Uint8Array(bytes);\n\tcrypto.getRandomValues(randomBytesArray);\n\treturn fromBytes(randomBytesArray, encoding);\n}\n\n/**\n * Generate a random private key\n */\nexport function generatePrivateKey(curve: CurveType = 'secp256k1', encoding: Encoding = 'base64url'): string | Uint8Array {\n\tlet keyBytes: Uint8Array;\n\n\tswitch (curve) {\n\t\tcase 'secp256k1':\n\t\t\tkeyBytes = secp256k1.utils.randomSecretKey();\n\t\t\tbreak;\n\t\tcase 'p256':\n\t\t\tkeyBytes = p256.utils.randomSecretKey();\n\t\t\tbreak;\n\t\tcase 'ed25519':\n\t\t\tkeyBytes = ed25519.utils.randomSecretKey();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported curve: ${curve}`);\n\t}\n\n\treturn fromBytes(keyBytes, encoding);\n}\n\n/**\n * Get public key from private key\n */\nexport function getPublicKey(\n\tprivateKey: string | Uint8Array,\n\tcurve: CurveType = 'secp256k1',\n\tkeyEncoding: Encoding = 'base64url',\n\toutputEncoding: Encoding = 'base64url'\n): string | Uint8Array {\n\tconst keyBytes = toBytes(privateKey, keyEncoding);\n\n\tlet pubBytes: Uint8Array;\n\n\tswitch (curve) {\n\t\tcase 'secp256k1':\n\t\t\tpubBytes = secp256k1.getPublicKey(keyBytes);\n\t\t\tbreak;\n\t\tcase 'p256':\n\t\t\tpubBytes = p256.getPublicKey(keyBytes);\n\t\t\tbreak;\n\t\tcase 'ed25519':\n\t\t\tpubBytes = ed25519.getPublicKey(keyBytes);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported curve: ${curve}`);\n\t}\n\n\treturn fromBytes(pubBytes, outputEncoding);\n}\n\n","/**\r\n * Quereus Plugin Entry Point for Crypto Functions\r\n *\r\n * This module provides the plugin registration following Quereus 0.4.5 format.\r\n * All metadata is in package.json - no manifest export needed.\r\n */\r\n\r\nimport type { Database, SqlValue } from '@quereus/quereus';\r\nimport { FunctionFlags, TEXT_TYPE, INTEGER_TYPE, BOOLEAN_TYPE } from '@quereus/quereus';\r\nimport { digest, sign, verify, hashMod, randomBytes } from './crypto.js';\r\n\r\n// Flags for deterministic functions (UTF8 + DETERMINISTIC)\r\nconst DETERMINISTIC_FLAGS = FunctionFlags.UTF8 | FunctionFlags.DETERMINISTIC;\r\n// Flags for non-deterministic functions (UTF8 only)\r\nconst NON_DETERMINISTIC_FLAGS = FunctionFlags.UTF8;\r\n\r\n/**\r\n * Plugin registration function\r\n * This is called by Quereus when the plugin is loaded\r\n */\r\nexport default function register(_db: Database, _config: Record<string, SqlValue> = {}) {\r\n\t// Register crypto functions with Quereus\r\n\tconst functions = [\r\n\t\t{\r\n\t\t\tschema: {\r\n\t\t\t\tname: 'digest',\r\n\t\t\t\tnumArgs: -1, // Variable arguments: data, algorithm?, inputEncoding?, outputEncoding?\r\n\t\t\t\tflags: DETERMINISTIC_FLAGS, // digest is deterministic\r\n\t\t\t\treturnType: { typeClass: 'scalar' as const, logicalType: TEXT_TYPE, nullable: false },\r\n\t\t\t\timplementation: (...args: SqlValue[]) => {\r\n\t\t\t\t\tconst [data, algorithm = 'sha256', inputEncoding = 'base64url', outputEncoding = 'base64url'] = args;\r\n\t\t\t\t\treturn digest(data as string, algorithm as any, inputEncoding as any, outputEncoding as any);\r\n\t\t\t\t},\r\n\t\t\t},\r\n\t\t},\r\n\t\t{\r\n\t\t\tschema: {\r\n\t\t\t\tname: 'sign',\r\n\t\t\t\tnumArgs: -1, // Variable arguments: data, privateKey, curve?, inputEncoding?, keyEncoding?, outputEncoding?\r\n\t\t\t\tflags: DETERMINISTIC_FLAGS, // sign is deterministic (same key + data = same signature)\r\n\t\t\t\treturnType: { typeClass: 'scalar' as const, logicalType: TEXT_TYPE, nullable: false },\r\n\t\t\t\timplementation: (...args: SqlValue[]) => {\r\n\t\t\t\t\tconst [data, privateKey, curve = 'secp256k1', inputEncoding = 'base64url', keyEncoding = 'base64url', outputEncoding = 'base64url'] = args;\r\n\t\t\t\t\treturn sign(data as string, privateKey as string, curve as any, inputEncoding as any, keyEncoding as any, outputEncoding as any);\r\n\t\t\t\t},\r\n\t\t\t},\r\n\t\t},\r\n\t\t{\r\n\t\t\tschema: {\r\n\t\t\t\tname: 'verify',\r\n\t\t\t\tnumArgs: -1, // Variable arguments: data, signature, publicKey, curve?, inputEncoding?, sigEncoding?, keyEncoding?\r\n\t\t\t\tflags: DETERMINISTIC_FLAGS, // verify is deterministic\r\n\t\t\t\treturnType: { typeClass: 'scalar' as const, logicalType: BOOLEAN_TYPE, nullable: false },\r\n\t\t\t\timplementation: (...args: SqlValue[]) => {\r\n\t\t\t\t\tconst [data, signature, publicKey, curve = 'secp256k1', inputEncoding = 'base64url', sigEncoding = 'base64url', keyEncoding = 'base64url'] = args;\r\n\t\t\t\t\tconst result = verify(data as string, signature as string, publicKey as string, curve as any, inputEncoding as any, sigEncoding as any, keyEncoding as any);\r\n\t\t\t\t\treturn result;\r\n\t\t\t\t},\r\n\t\t\t},\r\n\t\t},\r\n\t\t{\r\n\t\t\tschema: {\r\n\t\t\t\tname: 'hash_mod',\r\n\t\t\t\tnumArgs: -1, // Variable arguments: data, bits, algorithm?, inputEncoding?\r\n\t\t\t\tflags: DETERMINISTIC_FLAGS, // hash_mod is deterministic\r\n\t\t\t\treturnType: { typeClass: 'scalar' as const, logicalType: INTEGER_TYPE, nullable: false },\r\n\t\t\t\timplementation: (...args: SqlValue[]) => {\r\n\t\t\t\t\tconst [data, bits, algorithm = 'sha256', inputEncoding = 'base64url'] = args;\r\n\t\t\t\t\treturn hashMod(data as string, bits as number, algorithm as any, inputEncoding as any);\r\n\t\t\t\t},\r\n\t\t\t},\r\n\t\t},\r\n\t\t{\r\n\t\t\tschema: {\r\n\t\t\t\tname: 'random_bytes',\r\n\t\t\t\tnumArgs: -1, // Variable arguments: bits?, encoding?\r\n\t\t\t\tflags: NON_DETERMINISTIC_FLAGS, // random_bytes is NOT deterministic\r\n\t\t\t\treturnType: { typeClass: 'scalar' as const, logicalType: TEXT_TYPE, nullable: false },\r\n\t\t\t\timplementation: (...args: SqlValue[]) => {\r\n\t\t\t\t\tconst [bits = 256, encoding = 'base64url'] = args;\r\n\t\t\t\t\treturn randomBytes(bits as number, encoding as any);\r\n\t\t\t\t},\r\n\t\t\t},\r\n\t\t},\r\n\t];\r\n\r\n\treturn {\r\n\t\tfunctions,\r\n\t\tvtables: [],\r\n\t\tcollations: [],\r\n\t};\r\n}\r\n\r\n"]}
package/package.json CHANGED
@@ -1,71 +1,83 @@
1
1
  {
2
- "name": "@optimystic/quereus-plugin-crypto",
3
- "version": "0.2.0",
4
- "description": "Quereus plugin providing cryptographic functions (digest, sign, verify)",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "import": "./dist/index.js",
11
- "types": "./dist/index.d.ts"
12
- },
13
- "./plugin": {
14
- "import": "./dist/plugin.js",
15
- "types": "./dist/plugin.d.ts"
16
- }
17
- },
18
- "files": [
19
- "dist",
20
- "src",
21
- "README.md"
22
- ],
23
- "scripts": {
24
- "build": "tsup",
25
- "dev": "tsup --watch",
26
- "clean": "rm -rf dist",
27
- "typecheck": "tsc --noEmit"
28
- },
29
- "devDependencies": {
30
- "@quereus/quereus": "^0.4.5",
31
- "@types/node": "^24.0.12",
32
- "aegir": "^47.0.20",
33
- "tsup": "^8.5.0",
34
- "typescript": "^5.8.3"
35
- },
36
- "dependencies": {
37
- "@noble/curves": "^1.9.6",
38
- "@noble/hashes": "^1.8.0",
39
- "uint8arrays": "^5.1.0"
40
- },
41
- "peerDependencies": {
42
- "@quereus/quereus": "^0.4.5"
43
- },
44
- "engines": {
45
- "quereus": "^0.4.5"
46
- },
47
- "keywords": [
48
- "quereus-plugin",
49
- "quereus",
50
- "crypto",
51
- "cryptography",
52
- "digest",
53
- "hash",
54
- "signature",
55
- "sign",
56
- "verify",
57
- "secp256k1",
58
- "ed25519",
59
- "p256"
60
- ],
61
- "author": "Optimystic Team",
62
- "license": "MIT",
63
- "quereus": {
64
- "provides": {
65
- "functions": ["digest", "sign", "verify", "hash_mod", "random_bytes"],
66
- "vtables": [],
67
- "collations": []
68
- },
69
- "settings": []
70
- }
71
- }
2
+ "name": "@optimystic/quereus-plugin-crypto",
3
+ "version": "0.3.1",
4
+ "description": "Quereus plugin providing cryptographic functions (digest, sign, verify)",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./plugin": {
14
+ "import": "./dist/plugin.js",
15
+ "types": "./dist/plugin.d.ts"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "src",
21
+ "README.md"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "dev": "tsup --watch",
26
+ "clean": "rimraf dist",
27
+ "typecheck": "tsc --noEmit"
28
+ },
29
+ "devDependencies": {
30
+ "@quereus/quereus": "^0.16.2",
31
+ "@types/node": "^25.2.0",
32
+ "aegir": "^47.0.26",
33
+ "rimraf": "^6.1.2",
34
+ "tsup": "^8.5.1",
35
+ "typescript": "^5.9.3"
36
+ },
37
+ "dependencies": {
38
+ "@noble/curves": "^2.0.1",
39
+ "@noble/hashes": "^2.0.1",
40
+ "uint8arrays": "^5.1.0"
41
+ },
42
+ "peerDependencies": {
43
+ "@quereus/quereus": "^0.16.2"
44
+ },
45
+ "engines": {
46
+ "quereus": "^0.16.2"
47
+ },
48
+ "keywords": [
49
+ "quereus-plugin",
50
+ "quereus",
51
+ "crypto",
52
+ "cryptography",
53
+ "digest",
54
+ "hash",
55
+ "signature",
56
+ "sign",
57
+ "verify",
58
+ "secp256k1",
59
+ "ed25519",
60
+ "p256"
61
+ ],
62
+ "repository": {
63
+ "type": "git",
64
+ "url": "https://github.com/gotchoices/optimystic.git",
65
+ "directory": "packages/quereus-plugin-crypto"
66
+ },
67
+ "author": "Got Choices Foundation",
68
+ "license": "MIT",
69
+ "quereus": {
70
+ "provides": {
71
+ "functions": [
72
+ "digest",
73
+ "sign",
74
+ "verify",
75
+ "hash_mod",
76
+ "random_bytes"
77
+ ],
78
+ "vtables": [],
79
+ "collations": []
80
+ },
81
+ "settings": []
82
+ }
83
+ }
package/src/crypto.ts CHANGED
@@ -5,13 +5,13 @@
5
5
  * All functions accept and return base64url strings by default for SQL compatibility.
6
6
  */
7
7
 
8
- import { sha256, sha512 } from '@noble/hashes/sha2';
9
- import { blake3 } from '@noble/hashes/blake3';
10
- import { concatBytes, utf8ToBytes } from '@noble/hashes/utils';
11
- import { secp256k1 } from '@noble/curves/secp256k1';
12
- import { p256 } from '@noble/curves/nist';
13
- import { ed25519 } from '@noble/curves/ed25519';
14
- import { hexToBytes, bytesToHex } from '@noble/curves/abstract/utils';
8
+ import { sha256, sha512 } from '@noble/hashes/sha2.js';
9
+ import { blake3 } from '@noble/hashes/blake3.js';
10
+ import { concatBytes, utf8ToBytes } from '@noble/hashes/utils.js';
11
+ import { secp256k1 } from '@noble/curves/secp256k1.js';
12
+ import { p256 } from '@noble/curves/nist.js';
13
+ import { ed25519 } from '@noble/curves/ed25519.js';
14
+ import { hexToBytes, bytesToHex } from '@noble/curves/utils.js';
15
15
  import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays';
16
16
 
17
17
  // Type definitions
@@ -192,20 +192,15 @@ export function sign(
192
192
  let sigBytes: Uint8Array;
193
193
 
194
194
  switch (curve) {
195
- case 'secp256k1': {
196
- const sig = secp256k1.sign(dataBytes, keyBytes, { lowS: true });
197
- sigBytes = sig.toCompactRawBytes();
195
+ case 'secp256k1':
196
+ sigBytes = secp256k1.sign(dataBytes, keyBytes, { lowS: true });
198
197
  break;
199
- }
200
- case 'p256': {
201
- const sig = p256.sign(dataBytes, keyBytes, { lowS: true });
202
- sigBytes = sig.toCompactRawBytes();
198
+ case 'p256':
199
+ sigBytes = p256.sign(dataBytes, keyBytes, { lowS: true });
203
200
  break;
204
- }
205
- case 'ed25519': {
201
+ case 'ed25519':
206
202
  sigBytes = ed25519.sign(dataBytes, keyBytes);
207
203
  break;
208
- }
209
204
  default:
210
205
  throw new Error(`Unsupported curve: ${curve}`);
211
206
  }
@@ -288,13 +283,13 @@ export function generatePrivateKey(curve: CurveType = 'secp256k1', encoding: Enc
288
283
 
289
284
  switch (curve) {
290
285
  case 'secp256k1':
291
- keyBytes = secp256k1.utils.randomPrivateKey();
286
+ keyBytes = secp256k1.utils.randomSecretKey();
292
287
  break;
293
288
  case 'p256':
294
- keyBytes = p256.utils.randomPrivateKey();
289
+ keyBytes = p256.utils.randomSecretKey();
295
290
  break;
296
291
  case 'ed25519':
297
- keyBytes = ed25519.utils.randomPrivateKey();
292
+ keyBytes = ed25519.utils.randomSecretKey();
298
293
  break;
299
294
  default:
300
295
  throw new Error(`Unsupported curve: ${curve}`);
package/src/digest.ts CHANGED
@@ -6,10 +6,10 @@
6
6
  * Compatible with React Native and all JS environments.
7
7
  */
8
8
 
9
- import { sha256 } from '@noble/hashes/sha2';
10
- import { sha512 } from '@noble/hashes/sha2';
11
- import { blake3 } from '@noble/hashes/blake3';
12
- import { concatBytes, utf8ToBytes } from '@noble/hashes/utils';
9
+ import { sha256 } from '@noble/hashes/sha2.js';
10
+ import { sha512 } from '@noble/hashes/sha2.js';
11
+ import { blake3 } from '@noble/hashes/blake3.js';
12
+ import { concatBytes, utf8ToBytes } from '@noble/hashes/utils.js';
13
13
 
14
14
  /**
15
15
  * Hash algorithm options
package/src/plugin.ts CHANGED
@@ -1,87 +1,93 @@
1
- /**
2
- * Quereus Plugin Entry Point for Crypto Functions
3
- *
4
- * This module provides the plugin registration following Quereus 0.4.5 format.
5
- * All metadata is in package.json - no manifest export needed.
6
- */
7
-
8
- import type { Database, FunctionFlags, SqlValue } from '@quereus/quereus';
9
- import { digest, sign, verify, hashMod, randomBytes } from './crypto.js';
10
-
11
- /**
12
- * Plugin registration function
13
- * This is called by Quereus when the plugin is loaded
14
- */
15
- export default function register(_db: Database, _config: Record<string, SqlValue> = {}) {
16
- // Register crypto functions with Quereus
17
- const functions = [
18
- {
19
- schema: {
20
- name: 'digest',
21
- numArgs: -1, // Variable arguments: data, algorithm?, inputEncoding?, outputEncoding?
22
- flags: 1 as FunctionFlags, // UTF8
23
- returnType: { typeClass: 'scalar' as const, sqlType: 'TEXT' },
24
- implementation: (...args: SqlValue[]) => {
25
- const [data, algorithm = 'sha256', inputEncoding = 'base64url', outputEncoding = 'base64url'] = args;
26
- return digest(data as string, algorithm as any, inputEncoding as any, outputEncoding as any);
27
- },
28
- },
29
- },
30
- {
31
- schema: {
32
- name: 'sign',
33
- numArgs: -1, // Variable arguments: data, privateKey, curve?, inputEncoding?, keyEncoding?, outputEncoding?
34
- flags: 1 as FunctionFlags,
35
- returnType: { typeClass: 'scalar' as const, sqlType: 'TEXT' },
36
- implementation: (...args: SqlValue[]) => {
37
- const [data, privateKey, curve = 'secp256k1', inputEncoding = 'base64url', keyEncoding = 'base64url', outputEncoding = 'base64url'] = args;
38
- return sign(data as string, privateKey as string, curve as any, inputEncoding as any, keyEncoding as any, outputEncoding as any);
39
- },
40
- },
41
- },
42
- {
43
- schema: {
44
- name: 'verify',
45
- numArgs: -1, // Variable arguments: data, signature, publicKey, curve?, inputEncoding?, sigEncoding?, keyEncoding?
46
- flags: 1 as FunctionFlags,
47
- returnType: { typeClass: 'scalar' as const, sqlType: 'INTEGER' },
48
- implementation: (...args: SqlValue[]) => {
49
- const [data, signature, publicKey, curve = 'secp256k1', inputEncoding = 'base64url', sigEncoding = 'base64url', keyEncoding = 'base64url'] = args;
50
- const result = verify(data as string, signature as string, publicKey as string, curve as any, inputEncoding as any, sigEncoding as any, keyEncoding as any);
51
- return result ? 1 : 0;
52
- },
53
- },
54
- },
55
- {
56
- schema: {
57
- name: 'hash_mod',
58
- numArgs: -1, // Variable arguments: data, bits, algorithm?, inputEncoding?
59
- flags: 1 as FunctionFlags,
60
- returnType: { typeClass: 'scalar' as const, sqlType: 'INTEGER' },
61
- implementation: (...args: SqlValue[]) => {
62
- const [data, bits, algorithm = 'sha256', inputEncoding = 'base64url'] = args;
63
- return hashMod(data as string, bits as number, algorithm as any, inputEncoding as any);
64
- },
65
- },
66
- },
67
- {
68
- schema: {
69
- name: 'random_bytes',
70
- numArgs: -1, // Variable arguments: bits?, encoding?
71
- flags: 1 as FunctionFlags,
72
- returnType: { typeClass: 'scalar' as const, sqlType: 'TEXT' },
73
- implementation: (...args: SqlValue[]) => {
74
- const [bits = 256, encoding = 'base64url'] = args;
75
- return randomBytes(bits as number, encoding as any);
76
- },
77
- },
78
- },
79
- ];
80
-
81
- return {
82
- functions,
83
- vtables: [],
84
- collations: [],
85
- };
86
- }
87
-
1
+ /**
2
+ * Quereus Plugin Entry Point for Crypto Functions
3
+ *
4
+ * This module provides the plugin registration following Quereus 0.4.5 format.
5
+ * All metadata is in package.json - no manifest export needed.
6
+ */
7
+
8
+ import type { Database, SqlValue } from '@quereus/quereus';
9
+ import { FunctionFlags, TEXT_TYPE, INTEGER_TYPE, BOOLEAN_TYPE } from '@quereus/quereus';
10
+ import { digest, sign, verify, hashMod, randomBytes } from './crypto.js';
11
+
12
+ // Flags for deterministic functions (UTF8 + DETERMINISTIC)
13
+ const DETERMINISTIC_FLAGS = FunctionFlags.UTF8 | FunctionFlags.DETERMINISTIC;
14
+ // Flags for non-deterministic functions (UTF8 only)
15
+ const NON_DETERMINISTIC_FLAGS = FunctionFlags.UTF8;
16
+
17
+ /**
18
+ * Plugin registration function
19
+ * This is called by Quereus when the plugin is loaded
20
+ */
21
+ export default function register(_db: Database, _config: Record<string, SqlValue> = {}) {
22
+ // Register crypto functions with Quereus
23
+ const functions = [
24
+ {
25
+ schema: {
26
+ name: 'digest',
27
+ numArgs: -1, // Variable arguments: data, algorithm?, inputEncoding?, outputEncoding?
28
+ flags: DETERMINISTIC_FLAGS, // digest is deterministic
29
+ returnType: { typeClass: 'scalar' as const, logicalType: TEXT_TYPE, nullable: false },
30
+ implementation: (...args: SqlValue[]) => {
31
+ const [data, algorithm = 'sha256', inputEncoding = 'base64url', outputEncoding = 'base64url'] = args;
32
+ return digest(data as string, algorithm as any, inputEncoding as any, outputEncoding as any);
33
+ },
34
+ },
35
+ },
36
+ {
37
+ schema: {
38
+ name: 'sign',
39
+ numArgs: -1, // Variable arguments: data, privateKey, curve?, inputEncoding?, keyEncoding?, outputEncoding?
40
+ flags: DETERMINISTIC_FLAGS, // sign is deterministic (same key + data = same signature)
41
+ returnType: { typeClass: 'scalar' as const, logicalType: TEXT_TYPE, nullable: false },
42
+ implementation: (...args: SqlValue[]) => {
43
+ const [data, privateKey, curve = 'secp256k1', inputEncoding = 'base64url', keyEncoding = 'base64url', outputEncoding = 'base64url'] = args;
44
+ return sign(data as string, privateKey as string, curve as any, inputEncoding as any, keyEncoding as any, outputEncoding as any);
45
+ },
46
+ },
47
+ },
48
+ {
49
+ schema: {
50
+ name: 'verify',
51
+ numArgs: -1, // Variable arguments: data, signature, publicKey, curve?, inputEncoding?, sigEncoding?, keyEncoding?
52
+ flags: DETERMINISTIC_FLAGS, // verify is deterministic
53
+ returnType: { typeClass: 'scalar' as const, logicalType: BOOLEAN_TYPE, nullable: false },
54
+ implementation: (...args: SqlValue[]) => {
55
+ const [data, signature, publicKey, curve = 'secp256k1', inputEncoding = 'base64url', sigEncoding = 'base64url', keyEncoding = 'base64url'] = args;
56
+ const result = verify(data as string, signature as string, publicKey as string, curve as any, inputEncoding as any, sigEncoding as any, keyEncoding as any);
57
+ return result;
58
+ },
59
+ },
60
+ },
61
+ {
62
+ schema: {
63
+ name: 'hash_mod',
64
+ numArgs: -1, // Variable arguments: data, bits, algorithm?, inputEncoding?
65
+ flags: DETERMINISTIC_FLAGS, // hash_mod is deterministic
66
+ returnType: { typeClass: 'scalar' as const, logicalType: INTEGER_TYPE, nullable: false },
67
+ implementation: (...args: SqlValue[]) => {
68
+ const [data, bits, algorithm = 'sha256', inputEncoding = 'base64url'] = args;
69
+ return hashMod(data as string, bits as number, algorithm as any, inputEncoding as any);
70
+ },
71
+ },
72
+ },
73
+ {
74
+ schema: {
75
+ name: 'random_bytes',
76
+ numArgs: -1, // Variable arguments: bits?, encoding?
77
+ flags: NON_DETERMINISTIC_FLAGS, // random_bytes is NOT deterministic
78
+ returnType: { typeClass: 'scalar' as const, logicalType: TEXT_TYPE, nullable: false },
79
+ implementation: (...args: SqlValue[]) => {
80
+ const [bits = 256, encoding = 'base64url'] = args;
81
+ return randomBytes(bits as number, encoding as any);
82
+ },
83
+ },
84
+ },
85
+ ];
86
+
87
+ return {
88
+ functions,
89
+ vtables: [],
90
+ collations: [],
91
+ };
92
+ }
93
+
package/src/sign.ts CHANGED
@@ -6,10 +6,10 @@
6
6
  * Compatible with React Native and all JS environments.
7
7
  */
8
8
 
9
- import { secp256k1 } from '@noble/curves/secp256k1';
10
- import { p256 } from '@noble/curves/nist';
11
- import { ed25519 } from '@noble/curves/ed25519';
12
- import { bytesToHex, hexToBytes } from '@noble/curves/abstract/utils';
9
+ import { secp256k1 } from '@noble/curves/secp256k1.js';
10
+ import { p256 } from '@noble/curves/nist.js';
11
+ import { ed25519 } from '@noble/curves/ed25519.js';
12
+ import { bytesToHex, hexToBytes } from '@noble/curves/utils.js';
13
13
 
14
14
  /**
15
15
  * Supported elliptic curve types
@@ -83,35 +83,25 @@ function normalizeDigest(digest: DigestInput): Uint8Array {
83
83
  }
84
84
 
85
85
  /**
86
- * Format signature based on requested format
86
+ * Format signature based on requested format.
87
+ * In @noble/curves v2.0.1, sign() returns Uint8Array directly.
87
88
  */
88
- function formatSignature(signature: any, format: SignatureFormat, curve: CurveType): Uint8Array | string {
89
+ function formatSignature(signature: Uint8Array, format: SignatureFormat, curve: CurveType): Uint8Array | string {
89
90
  switch (format) {
90
91
  case 'uint8array':
91
- if (curve === 'ed25519') {
92
- return signature;
93
- }
94
- return signature.toCompactRawBytes();
92
+ case 'compact':
93
+ return signature;
95
94
 
96
95
  case 'hex':
97
- if (curve === 'ed25519') {
98
- return bytesToHex(signature);
99
- }
100
- return signature.toCompactHex();
101
-
102
- case 'compact':
103
- if (curve === 'ed25519') {
104
- return signature;
105
- }
106
- return signature.toCompactRawBytes();
96
+ return bytesToHex(signature);
107
97
 
108
98
  case 'der':
109
99
  if (curve === 'ed25519') {
110
100
  throw new Error('DER format not supported for ed25519');
111
101
  }
112
- // Note: DER encoding would require additional implementation
113
- // For now, fall back to compact
114
- return signature.toCompactRawBytes();
102
+ // DER format requires the sign() call to request it via format option
103
+ // For now, return compact format as fallback
104
+ return signature;
115
105
 
116
106
  default:
117
107
  throw new Error(`Unsupported signature format: ${format}`);
@@ -214,11 +204,11 @@ Sign.ed25519 = (digest: DigestInput, privateKey: PrivateKeyInput, options: Omit<
214
204
  Sign.generatePrivateKey = (curve: CurveType = 'secp256k1'): Uint8Array => {
215
205
  switch (curve) {
216
206
  case 'secp256k1':
217
- return secp256k1.utils.randomPrivateKey();
207
+ return secp256k1.utils.randomSecretKey();
218
208
  case 'p256':
219
- return p256.utils.randomPrivateKey();
209
+ return p256.utils.randomSecretKey();
220
210
  case 'ed25519':
221
- return ed25519.utils.randomPrivateKey();
211
+ return ed25519.utils.randomSecretKey();
222
212
  default:
223
213
  throw new Error(`Unsupported curve: ${curve}`);
224
214
  }