Node.js
const fs = require(‘fs’);
const { execFile } = require(‘child_process’);
const { promisify } = require(‘util’);
const crypto = require(‘crypto’);
const os = require(‘os’);
const path = require(‘path’);
const execAsync = promisify(execFile);
/**
* Request an RFC 3161 timestamp for a file.
* @param {string} filePath – Path to the file to timestamp
* @returns {Promise<Buffer>} TSR as Buffer
*/
async function timestamp(filePath) {
const id = crypto.randomBytes(8).toString(‘hex’);
const tsq = path.join(os.tmpdir(), `${id}.tsq`);
await execAsync(‘openssl’, [
‘ts’, ‘-query’, ‘-data’, filePath,
‘-cert’, ‘-sha256’, ‘-no_nonce’, ‘-out’, tsq
]);
const body = fs.readFileSync(tsq);
fs.unlinkSync(tsq);
const response = await fetch(
process.env.TSA_URL || ‘https://tsr.open-tsa.eu‘,
{
method: ‘POST’,
headers: { ‘Content-Type’: ‘application/timestamp-query’ },
body,
}
);
if (!response.ok) {
throw new Error(`TSA error: ${response.status} ${response.statusText}`);
}
return Buffer.from(await response.arrayBuffer());
}
// Usage
timestamp(‘./document.pdf’)
.then(tsr => {
fs.writeFileSync(‘./document.tsr’, tsr);
console.log(‘Timestamp saved to document.tsr’);
})
.catch(console.error);
.env configuration
TSA_URL=https://tsr.open-tsa.eu
Node.js version: The
fetch API is available natively in Node.js 18+. For older versions, use node-fetch or axios.