fix:
- AES GCM protocol mismatch - better, granular error handling - UUID now uses crypto.randomUUID() - added native mlock addon to improve security - ZeroBuffer uses explicit_bzero now - fixed imports feat: - added unit tests
This commit is contained in:
parent
0b09b9a9c3
commit
c7601b2270
17 changed files with 12600 additions and 164 deletions
|
|
@ -1,41 +1,105 @@
|
|||
/**
|
||||
* Node.js secure memory implementation (pure JavaScript)
|
||||
*
|
||||
* LIMITATIONS:
|
||||
* - This is a pure JavaScript implementation without native addons
|
||||
* - Cannot lock memory (no mlock support without native addon)
|
||||
* - JavaScript GC controls memory lifecycle
|
||||
* - Best effort: immediate zeroing to minimize exposure time
|
||||
*
|
||||
* FUTURE ENHANCEMENT:
|
||||
* A native addon can be implemented separately to provide true mlock support.
|
||||
* See the native/ directory for an optional native implementation.
|
||||
* Node.js secure memory implementation.
|
||||
*
|
||||
* When the optional native addon (nomyo-native) is installed and built,
|
||||
* this implementation provides true OS-level memory locking (mlock) and
|
||||
* secure zeroing via explicit_bzero / SecureZeroMemory.
|
||||
*
|
||||
* Without the native addon it falls back to pure-JS zeroing only.
|
||||
*
|
||||
* To build the native addon:
|
||||
* cd native && npm install && npm run build
|
||||
*/
|
||||
|
||||
import { SecureMemory, ProtectionInfo } from '../../types/crypto';
|
||||
import { SecureMemory } from './secure';
|
||||
import { ProtectionInfo } from '../../types/crypto';
|
||||
|
||||
interface NativeAddon {
|
||||
mlockBuffer(buf: Buffer): boolean;
|
||||
munlockBuffer(buf: Buffer): boolean;
|
||||
secureZeroBuffer(buf: Buffer): void;
|
||||
getPageSize(): number;
|
||||
}
|
||||
|
||||
// Try to load the optional native addon once at module init time.
|
||||
let nativeAddon: NativeAddon | null = null;
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const loaded = require('nomyo-native') as NativeAddon | null;
|
||||
if (loaded && typeof loaded.mlockBuffer === 'function') {
|
||||
nativeAddon = loaded;
|
||||
}
|
||||
} catch (_e) {
|
||||
// Native addon not installed — degrade gracefully
|
||||
}
|
||||
|
||||
export class NodeSecureMemory implements SecureMemory {
|
||||
private readonly hasNative: boolean;
|
||||
|
||||
constructor() {
|
||||
this.hasNative = nativeAddon !== null;
|
||||
if (this.hasNative) {
|
||||
console.log('nomyo-native addon loaded: mlock + secure-zero available');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zero memory immediately
|
||||
* Note: This doesn't prevent JavaScript GC from moving/copying the data
|
||||
* Zero memory.
|
||||
* With native addon: uses explicit_bzero / SecureZeroMemory (not optimized away).
|
||||
* Without native addon: fills ArrayBuffer with zeros via Uint8Array (best effort).
|
||||
*/
|
||||
zeroMemory(data: ArrayBuffer): void {
|
||||
if (this.hasNative && nativeAddon) {
|
||||
// Buffer.from(arrayBuffer) shares the underlying memory (no copy)
|
||||
const buf = Buffer.from(data);
|
||||
nativeAddon.secureZeroBuffer(buf);
|
||||
}
|
||||
// Always also zero via JS for defence-in-depth
|
||||
const view = new Uint8Array(data);
|
||||
view.fill(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get protection information
|
||||
* Attempt to lock an ArrayBuffer in physical memory (prevent swapping).
|
||||
* Best-effort: fails gracefully without CAP_IPC_LOCK / elevated privileges.
|
||||
*/
|
||||
lockMemory(data: ArrayBuffer): boolean {
|
||||
if (!this.hasNative || !nativeAddon) return false;
|
||||
const buf = Buffer.from(data);
|
||||
return nativeAddon.mlockBuffer(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock previously locked memory.
|
||||
*/
|
||||
unlockMemory(data: ArrayBuffer): boolean {
|
||||
if (!this.hasNative || !nativeAddon) return false;
|
||||
const buf = Buffer.from(data);
|
||||
return nativeAddon.munlockBuffer(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory protection information.
|
||||
*/
|
||||
getProtectionInfo(): ProtectionInfo {
|
||||
if (this.hasNative) {
|
||||
return {
|
||||
canLock: true,
|
||||
isPlatformSecure: true,
|
||||
method: 'mlock',
|
||||
details:
|
||||
'Node.js with nomyo-native addon: mlock + explicit_bzero/SecureZeroMemory available.',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
canLock: false,
|
||||
isPlatformSecure: false,
|
||||
method: 'zero-only',
|
||||
details:
|
||||
'Node.js environment (pure JS): memory locking not available without native addon. ' +
|
||||
'Node.js (pure JS): memory locking not available without native addon. ' +
|
||||
'Using immediate zeroing only. ' +
|
||||
'For enhanced security, consider implementing the optional native addon (see native/ directory).',
|
||||
'Build the optional native addon for mlock support: cd native && npm install && npm run build',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue