const crypto = require('crypto');
const fs = require('fs');
const { promisify } = require('util');
const { exec } = require('child_process');
const execAsync = promisify(exec);
// Message to sign and verify
const message = 'Message to verify with certificate';
const privateKeyPath = 'private_key.pem';
const certPath = 'certificate.pem';
const messagePath = 'message.txt';
const signaturePath = 'signature.bin';
// Generate a self-signed certificate and private key if they don't exist
async function generateCertificate() {
try {
// Check if certificate already exists
await fs.promises.access(certPath);
console.log('Using existing certificate and private key');
} catch {
console.log('Generating new self-signed certificate and private key...');
// Generate private key
await execAsync(`openssl genrsa -out ${privateKeyPath} 2048`);
// Generate self-signed certificate
await execAsync(
`openssl req -new -x509 -key ${privateKeyPath} -out ${certPath} -days 365 -subj "/C=US/ST=State/L=City/O=Organization/CN=example.com"`
);
console.log('Certificate and private key generated');
}
}
// Sign a message using the private key
async function signMessage() {
try {
// Write message to file
await fs.promises.writeFile(messagePath, message);
// Sign the message
await execAsync(
`openssl dgst -sha256 -sign ${privateKeyPath} -out ${signaturePath} ${messagePath}`
);
console.log('Message signed successfully');
return true;
} catch (error) {
console.error('Error signing message:', error);
return false;
}
}
// Verify the signature using the certificate
async function verifyWithCertificate() {
try {
// Verify the signature
const { stdout, stderr } = await execAsync(
`openssl dgst -sha256 -verify <(openssl x509 -in ${certPath} -pubkey -noout) -signature ${signaturePath} ${messagePath}`
);
if (stderr) {
console.error('Verification error:', stderr);
return false;
}
console.log('Verification result:', stdout.trim());
return stdout.includes('Verified OK');
} catch (error) {
console.error('Error verifying signature:', error.message);
console.error('stderr:', error.stderr);
return false;
}
}
// Clean up generated files
async function cleanup() {
try {
await Promise.all([
fs.promises.unlink(privateKeyPath).catch(() => {}),
fs.promises.unlink(certPath).catch(() => {}),
fs.promises.unlink(messagePath).catch(() => {}),
fs.promises.unlink(signaturePath).catch(() => {})
]);
} catch (error) {
console.error('Error during cleanup:', error.message);
}
}
// Main function
async function main() {
try {
// Generate certificate if needed
await generateCertificate();
// Sign the message
const signed = await signMessage();
if (!signed) {
throw new Error('Failed to sign message');
}
// Verify the signature using the certificate
const isValid = await verifyWithCertificate();
// Try with tampered message (should fail)
if (isValid) {
console.log('\nTesting with tampered message...');
await fs.promises.appendFile(messagePath, ' (tampered)');
await verifyWithCertificate();
}
// Show certificate info
console.log('\nCertificate information:');
const { stdout: certInfo } = await execAsync(`openssl x509 -in ${certPath} -noout -text | head -n 20`);
console.log(certInfo);
} catch (error) {
console.error('Error in main:', error);
} finally {
// Clean up files
// Uncomment the next line to clean up after testing
// await cleanup();
}
}
// Run the example
main().catch(console.error);