Skip to content
Snippets Groups Projects
tls.js 4.89 KiB
Newer Older
  • Learn to ignore specific revisions
  • Zdravko Iliev's avatar
    Zdravko Iliev committed
    var forge = require('..');
    
    // function to create certificate
    var createCert = function(cn, data) {
      console.log(
        'Generating 512-bit key-pair and certificate for \"' + cn + '\".');
      var keys = forge.pki.rsa.generateKeyPair(512);
      console.log('key-pair created.');
    
      var cert = forge.pki.createCertificate();
      cert.serialNumber = '01';
      cert.validity.notBefore = new Date();
      cert.validity.notAfter = new Date();
      cert.validity.notAfter.setFullYear(
        cert.validity.notBefore.getFullYear() + 1);
      var attrs = [{
        name: 'commonName',
        value: cn
      }, {
        name: 'countryName',
        value: 'US'
      }, {
        shortName: 'ST',
        value: 'Virginia'
      }, {
        name: 'localityName',
        value: 'Blacksburg'
      }, {
        name: 'organizationName',
        value: 'Test'
      }, {
        shortName: 'OU',
        value: 'Test'
      }];
      cert.setSubject(attrs);
      cert.setIssuer(attrs);
      cert.setExtensions([{
        name: 'basicConstraints',
        cA: true
      }, {
        name: 'keyUsage',
        keyCertSign: true,
        digitalSignature: true,
        nonRepudiation: true,
        keyEncipherment: true,
        dataEncipherment: true
      }, {
        name: 'subjectAltName',
        altNames: [{
          type: 6, // URI
          value: 'http://myuri.com/webid#me'
        }]
      }]);
      // FIXME: add subjectKeyIdentifier extension
      // FIXME: add authorityKeyIdentifier extension
      cert.publicKey = keys.publicKey;
    
      // self-sign certificate
      cert.sign(keys.privateKey);
    
      // save data
      data[cn] = {
        cert: forge.pki.certificateToPem(cert),
        privateKey: forge.pki.privateKeyToPem(keys.privateKey)
      };
    
      console.log('certificate created for \"' + cn + '\": \n' + data[cn].cert);
    };
    
    var end = {};
    var data = {};
    
    // create certificate for server and client
    createCert('server', data);
    createCert('client', data);
    
    var success = false;
    
    // create TLS client
    end.client = forge.tls.createConnection({
      server: false,
      caStore: [data.server.cert],
      sessionCache: {},
      // supported cipher suites in order of preference
      cipherSuites: [
        forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
        forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
      virtualHost: 'server',
      verify: function(c, verified, depth, certs) {
        console.log(
          'TLS Client verifying certificate w/CN: \"' +
          certs[0].subject.getField('CN').value +
          '\", verified: ' + verified + '...');
        return verified;
      },
      connected: function(c) {
        console.log('Client connected...');
    
        // send message to server
        setTimeout(function() {
          c.prepareHeartbeatRequest('heartbeat');
          c.prepare('Hello Server');
        }, 1);
      },
      getCertificate: function(c, hint) {
        console.log('Client getting certificate ...');
        return data.client.cert;
      },
      getPrivateKey: function(c, cert) {
        return data.client.privateKey;
      },
      tlsDataReady: function(c) {
        // send TLS data to server
        end.server.process(c.tlsData.getBytes());
      },
      dataReady: function(c) {
        var response = c.data.getBytes();
        console.log('Client received \"' + response + '\"');
        success = (response === 'Hello Client');
        c.close();
      },
      heartbeatReceived: function(c, payload) {
        console.log('Client received heartbeat: ' + payload.getBytes());
      },
      closed: function(c) {
        console.log('Client disconnected.');
        if(success) {
          console.log('PASS');
        } else {
          console.log('FAIL');
        }
      },
      error: function(c, error) {
        console.log('Client error: ' + error.message);
      }
    });
    
    // create TLS server
    end.server = forge.tls.createConnection({
      server: true,
      caStore: [data.client.cert],
      sessionCache: {},
      // supported cipher suites in order of preference
      cipherSuites: [
        forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
        forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
      connected: function(c) {
        console.log('Server connected');
        c.prepareHeartbeatRequest('heartbeat');
      },
      verifyClient: true,
      verify: function(c, verified, depth, certs) {
        console.log(
          'Server verifying certificate w/CN: \"' +
          certs[0].subject.getField('CN').value +
          '\", verified: ' + verified + '...');
        return verified;
      },
      getCertificate: function(c, hint) {
        console.log('Server getting certificate for \"' + hint[0] + '\"...');
        return data.server.cert;
      },
      getPrivateKey: function(c, cert) {
        return data.server.privateKey;
      },
      tlsDataReady: function(c) {
        // send TLS data to client
        end.client.process(c.tlsData.getBytes());
      },
      dataReady: function(c) {
        console.log('Server received \"' + c.data.getBytes() + '\"');
    
        // send response
        c.prepare('Hello Client');
        c.close();
      },
      heartbeatReceived: function(c, payload) {
        console.log('Server received heartbeat: ' + payload.getBytes());
      },
      closed: function(c) {
        console.log('Server disconnected.');
      },
      error: function(c, error) {
        console.log('Server error: ' + error.message);
      }
    });
    
    console.log('created TLS client and server, doing handshake...');
    end.client.handshake();