Get your own Node server
const tls = require('tls');
const fs = require('fs');
const crypto = require('crypto');
const { createServer } = require('net');
const { promisify } = require('util');
const writeFile = promisify(fs.writeFile);

console.log('ECDH with TLS Example');
console.log('='.repeat(50));

// Configuration
const PORT = 8443;
const HOST = '127.0.0.1';
const CURVE = 'prime256v1';
const MESSAGE = 'Hello from TLS with ECDH!';

// Generate self-signed certificate and key for testing
async function generateCert() {
  console.log('Generating self-signed certificate...');
  
  // Generate ECDSA key pair
  const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
    namedCurve: CURVE,
    publicKeyEncoding: { type: 'spki', format: 'pem' },
    privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
  });
  
  // Create self-signed certificate
  const cert = crypto.createCertificate({
    serialNumber: '01',
    subject: { CN: 'localhost' },
    issuer: { CN: 'localhost' },
    notBefore: new Date(),
    notAfter: new Date(Date.now() + 24 * 60 * 60 * 1000), // 1 day
    key: privateKey,
    extensions: [
      { name: 'basicConstraints', cA: true },
      { 
        name: 'subjectAltName',
        altNames: [
          { type: 2, value: 'localhost' },
          { type: 7, ip: '127.0.0.1' }
        ]
      }
    ]
  });
  
  return { cert, key: privateKey };
}

async function runTlsServer() {
  const { cert, key } = await generateCert();
  
  const options = {
    key,
    cert,
    // Enable ECDH cipher suites
    ciphers: [
      'ECDHE-ECDSA-AES128-GCM-SHA256',
      'ECDHE-ECDSA-AES256-GCM-SHA384',
      'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256',
      'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384'
    ].join(':'),
    // Set the curve to use for ECDH key exchange
    ecdhCurve: CURVE,
    // Only use TLS 1.2 or higher
    minVersion: 'TLSv1.2',
    // Disable old and insecure protocols
    maxVersion: 'TLSv1.3',
    // Require client certificate (for mutual TLS)
    requestCert: false,
    rejectUnauthorized: false
  };
  
  // Create TLS server
  const server = tls.createServer(options, (socket) => {
    console.log('Server: Client connected');
    
    // Log TLS session info
    const tlsSocket = socket;
    console.log('Server: Cipher:', tlsSocket.getCipher());
    console.log('Server: Protocol:', tlsSocket.getProtocol());
    console.log('Server: Ephemeral key:', tlsSocket.getEphemeralKeyInfo());
    
    // Handle incoming data
    socket.on('data', (data) => {
      console.log(`Server received: ${data}`);
      socket.write(`Echo: ${data}`);
    });
    
    // Handle errors
    socket.on('error', (error) => {
      console.error('Server error:', error);
    });
    
    // Handle connection end
    socket.on('end', () => {
      console.log('Server: Client disconnected');
    });
  });
  
  // Start listening
  server.listen(PORT, HOST, () => {
    console.log(`Server listening on ${HOST}:${PORT}`);
    console.log(`Using ECDH curve: ${CURVE}`);
  });
  
  return server;
}

async function runTlsClient() {
  // Wait for server to start
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  console.log('\nConnecting to server...');
  
  const options = {
    host: HOST,
    port: PORT,
    // Allow self-signed certificates
    rejectUnauthorized: false,
    // Enable ECDH cipher suites
    ciphers: [
      'ECDHE-ECDSA-AES128-GCM-SHA256',
      'ECDHE-ECDSA-AES256-GCM-SHA384',
      'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256',
      'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384'
    ].join(':'),
    // Set the curve to use for ECDH key exchange
    ecdhCurve: CURVE,
    // Only use TLS 1.2 or higher
    minVersion: 'TLSv1.2',
    // Disable old and insecure protocols
    maxVersion: 'TLSv1.3'
  };
  
  const client = tls.connect(options, () => {
    console.log('Client: Connected to server');
    console.log('Client: Cipher:', client.getCipher());
    console.log('Client: Protocol:', client.getProtocol());
    console.log('Client: Ephemeral key:', client.getEphemeralKeyInfo());
    
    // Send a message to the server
    console.log(`Client sending: ${MESSAGE}`);
    client.write(MESSAGE);
  });
  
  // Handle incoming data
  client.on('data', (data) => {
    console.log(`Client received: ${data}`);
    // Close the connection after receiving the response
    client.end();
  });
  
  // Handle connection end
  client.on('end', () => {
    console.log('Client: Connection closed');
  });
  
  // Handle errors
  client.on('error', (error) => {
    console.error('Client error:', error);
  });
  
  return client;
}

// Run the example
async function runExample() {
  try {
    // Start the server
    const server = await runTlsServer();
    
    // Run the client
    const client = await runTlsClient();
    
    // Close everything after a delay
    setTimeout(() => {
      client.end();
      server.close();
      console.log('Example completed');
    }, 5000);
    
  } catch (error) {
    console.error('Error:', error);
  }
}

// Run the example
runExample();

              
ECDH with TLS Example
==================================================
Generating self-signed certificate...
Server listening on 127.0.0.1:8443
Using ECDH curve: prime256v1

Connecting to server...
Server: Client connected
Server: Cipher: {
  name: 'ECDHE-ECDSA-AES128-GCM-SHA256',
  version: 'TLSv1.2'
}
Server: Protocol: TLSv1.2
Server: Ephemeral key: { type: 'EC', name: 'prime256v1', size: 256 }
Client: Connected to server
Client: Cipher: {
  name: 'ECDHE-ECDSA-AES128-GCM-SHA256',
  version: 'TLSv1.2'
}
Client: Protocol: TLSv1.2
Client: Ephemeral key: { type: 'EC', name: 'prime256v1', size: 256 }
Client sending: Hello from TLS with ECDH!
Server received: Hello from TLS with ECDH!
Client received: Echo: Hello from TLS with ECDH!
Client: Connection closed
Server: Client disconnected
Example completed