/** * Host openssl-compatible subset using bare-crypto (no OpenSSL binary). * Supported: `version`, `rand -hex N`, `dgst -sha256 [-binary] PATH`. */ import { createHash, randomBytes } from 'bare-crypto' import b4a from 'b4a' /** * @param {Record} ctx * @param {string[]} argv */ export async function runOpensslCli(ctx, argv) { const args = argv.slice(1).filter((a) => a !== '--') if ( args.length === 0 || args[0] === '-h' || args[0] === '-help' || args[0] === '--help' ) { ctx.console.log( 'usage: openssl version\n' + ' openssl rand -hex NUM_BYTES\n' + ' openssl dgst -sha256 [-binary] FILE\n' + 'Bare OS: bare-crypto backend (not OpenSSL).\n' ) return } if (args[0] === 'version') { ctx.console.log('Bare OS openssl compatibility (bare-crypto)') return } if (args[0] === 'rand') { let hex = false let n = 32 for (let i = 1; i < args.length; i++) { if (args[i] === '-hex') hex = true else if (/^\d+$/.test(args[i])) n = Number.parseInt(args[i], 10) } if (!hex) { ctx.console.error('openssl rand: only `openssl rand -hex NUM_BYTES` is supported') ctx.exitCode = 1 return } if (!Number.isFinite(n) || n < 1 || n > 65536) { ctx.console.error('openssl rand: invalid size') ctx.exitCode = 1 return } const raw = randomBytes(n) ctx.console.log(Buffer.from(raw).toString('hex')) return } if (args[0] === 'dgst') { let binary = false let i = 1 for (; i < args.length; i++) { if (args[i] === '-sha256') continue if (args[i] === '-binary') { binary = true continue } if (args[i].startsWith('-')) { ctx.console.error('openssl dgst: unsupported flag ' + args[i]) ctx.exitCode = 1 return } break } const filePath = args[i] if (!filePath) { ctx.console.error('openssl dgst: missing file') ctx.exitCode = 1 return } const vfs = ctx.vfs if (!vfs || typeof vfs.readFile !== 'function') { ctx.console.error('openssl dgst: vfs.readFile unavailable') ctx.exitCode = 1 return } let abs try { abs = vfs.resolveLogical(String(filePath)) } catch { ctx.console.error('openssl dgst: bad path') ctx.exitCode = 1 return } let buf try { buf = await vfs.readFile(abs) } catch (e) { ctx.console.error( 'openssl dgst: ' + ((e && /** @type {Error} */ (e).message) || String(e)) ) ctx.exitCode = 1 return } const h = createHash('sha256') h.update(b4a.isBuffer(buf) ? buf : new Uint8Array(buf)) const digest = h.digest() if (binary) { const u8 = digest instanceof Uint8Array ? digest : typeof Buffer !== 'undefined' ? new Uint8Array(Buffer.from(digest)) : new Uint8Array(0) if (typeof ctx.bareOsBinWrite === 'function') { ctx.bareOsBinWrite(u8) } else { ctx.console.error( 'openssl dgst -binary: binary stdout requires ctx.bareOsBinWrite' ) ctx.exitCode = 1 } } else { const hex = typeof digest === 'string' ? digest : typeof Buffer !== 'undefined' ? Buffer.from(digest).toString('hex') : [...new Uint8Array(digest)] .map((b) => b.toString(16).padStart(2, '0')) .join('') ctx.console.log(hex + ' *' + filePath) } return } ctx.console.error('openssl: unsupported command ' + args[0]) ctx.exitCode = 1 }