brainy/dist/universal/crypto.js
David Snelling f8c45f2d8d Initial commit: Brainy - Multi-Dimensional AI Database
Open source vector database with HNSW indexing, graph relationships,
and metadata facets. Features CLI with professional augmentation registry
integration for discovering extensions and capabilities.
2025-08-18 17:35:06 -07:00

215 lines
No EOL
6.5 KiB
JavaScript

/**
* Universal Crypto implementation
* Works in all environments: Browser, Node.js, Serverless
*/
import { isBrowser, isNode } from '../utils/environment.js';
let nodeCrypto = null;
// Dynamic import for Node.js crypto (only in Node.js environment)
if (isNode()) {
try {
nodeCrypto = await import('crypto');
}
catch {
// Ignore import errors in non-Node environments
}
}
/**
* Generate random bytes
*/
export function randomBytes(size) {
if (isBrowser() || typeof crypto !== 'undefined') {
// Use Web Crypto API (available in browsers and modern Node.js)
const array = new Uint8Array(size);
crypto.getRandomValues(array);
return array;
}
else if (nodeCrypto) {
// Use Node.js crypto as fallback
return new Uint8Array(nodeCrypto.randomBytes(size));
}
else {
// Fallback for environments without crypto
const array = new Uint8Array(size);
for (let i = 0; i < size; i++) {
array[i] = Math.floor(Math.random() * 256);
}
return array;
}
}
/**
* Generate random UUID
*/
export function randomUUID() {
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
return crypto.randomUUID();
}
else if (nodeCrypto && nodeCrypto.randomUUID) {
return nodeCrypto.randomUUID();
}
else {
// Fallback UUID generation
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
}
/**
* Create hash (simplified interface)
*/
export function createHash(algorithm) {
if (nodeCrypto && nodeCrypto.createHash) {
return nodeCrypto.createHash(algorithm);
}
else {
// Simple fallback hash for browsers (not cryptographically secure)
let hash = 0;
const hashObj = {
update: (data) => {
const text = typeof data === 'string' ? data : new TextDecoder().decode(data);
for (let i = 0; i < text.length; i++) {
const char = text.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash; // Convert to 32-bit integer
}
return hashObj;
},
digest: (encoding) => {
return Math.abs(hash).toString(16);
}
};
return hashObj;
}
}
/**
* Create HMAC
*/
export function createHmac(algorithm, key) {
if (nodeCrypto && nodeCrypto.createHmac) {
return nodeCrypto.createHmac(algorithm, key);
}
else {
// Fallback HMAC implementation (simplified)
return createHash(algorithm);
}
}
/**
* PBKDF2 synchronous
*/
export function pbkdf2Sync(password, salt, iterations, keylen, digest) {
if (nodeCrypto && nodeCrypto.pbkdf2Sync) {
return new Uint8Array(nodeCrypto.pbkdf2Sync(password, salt, iterations, keylen, digest));
}
else {
// Simplified fallback (not cryptographically secure)
const result = new Uint8Array(keylen);
const passwordStr = typeof password === 'string' ? password : new TextDecoder().decode(password);
const saltStr = typeof salt === 'string' ? salt : new TextDecoder().decode(salt);
let hash = 0;
const combined = passwordStr + saltStr;
for (let i = 0; i < combined.length; i++) {
hash = ((hash << 5) - hash) + combined.charCodeAt(i);
hash = hash & hash;
}
for (let i = 0; i < keylen; i++) {
result[i] = (Math.abs(hash + i) % 256);
}
return result;
}
}
/**
* Scrypt synchronous
*/
export function scryptSync(password, salt, keylen, options) {
if (nodeCrypto && nodeCrypto.scryptSync) {
return new Uint8Array(nodeCrypto.scryptSync(password, salt, keylen, options));
}
else {
// Fallback to pbkdf2Sync
return pbkdf2Sync(password, salt, 10000, keylen, 'sha256');
}
}
/**
* Create cipher
*/
export function createCipheriv(algorithm, key, iv) {
if (nodeCrypto && nodeCrypto.createCipheriv) {
return nodeCrypto.createCipheriv(algorithm, key, iv);
}
else {
// Fallback encryption (XOR-based, not secure)
let encrypted = '';
return {
update: (data, inputEncoding, outputEncoding) => {
for (let i = 0; i < data.length; i++) {
const char = data.charCodeAt(i);
const keyByte = key[i % key.length];
const ivByte = iv[i % iv.length];
encrypted += String.fromCharCode(char ^ keyByte ^ ivByte);
}
return outputEncoding === 'hex' ? Buffer.from(encrypted, 'binary').toString('hex') : encrypted;
},
final: (outputEncoding) => {
return outputEncoding === 'hex' ? '' : '';
}
};
}
}
/**
* Create decipher
*/
export function createDecipheriv(algorithm, key, iv) {
if (nodeCrypto && nodeCrypto.createDecipheriv) {
return nodeCrypto.createDecipheriv(algorithm, key, iv);
}
else {
// Fallback decryption (XOR-based, matches createCipheriv)
let decrypted = '';
return {
update: (data, inputEncoding, outputEncoding) => {
const input = inputEncoding === 'hex' ? Buffer.from(data, 'hex').toString('binary') : data;
for (let i = 0; i < input.length; i++) {
const char = input.charCodeAt(i);
const keyByte = key[i % key.length];
const ivByte = iv[i % iv.length];
decrypted += String.fromCharCode(char ^ keyByte ^ ivByte);
}
return decrypted;
},
final: (outputEncoding) => {
return '';
}
};
}
}
/**
* Timing safe equal
*/
export function timingSafeEqual(a, b) {
if (nodeCrypto && nodeCrypto.timingSafeEqual) {
return nodeCrypto.timingSafeEqual(a, b);
}
else {
// Fallback implementation
if (a.length !== b.length)
return false;
let result = 0;
for (let i = 0; i < a.length; i++) {
result |= a[i] ^ b[i];
}
return result === 0;
}
}
export default {
randomBytes,
randomUUID,
createHash,
createHmac,
pbkdf2Sync,
scryptSync,
createCipheriv,
createDecipheriv,
timingSafeEqual
};
//# sourceMappingURL=crypto.js.map