Get your own Node server
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);

              
Using existing certificate and private key
Message signed successfully
Verification result: Verified OK

Testing with tampered message...
Verification result: Verification Failure

Certificate information:
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            12:34:56:78:9a:bc:de:f1:23:45:67:89:ab:cd:ef:01:23:45:67:89
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = State, L = City, O = Organization, CN = example.com
        Validity
            Not Before: Jun 18 09:00:00 2025 GMT
            Not After : Jun 18 09:00:00 2026 GMT
        Subject: C = US, ST = State, L = City, O = Organization, CN = example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)