var sys = require('sys'); var ws = require('./ws'); var forge = require('../js/forge'); // function to create certificate var createCert = function(cn, data) { sys.puts( 'Generating 512-bit key-pair and certificate for \"' + cn + '\".'); var keys = forge.pki.rsa.generateKeyPair(512); sys.puts('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) }; sys.puts('certificate created for \"' + cn + '\": \n' + data[cn].cert); }; var data = {}; // create certificate for server createCert('server', data); // function to create TLS server connection var createTls = function(websocket) { return forge.tls.createConnection( { server: true, caStore: [], 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) { sys.puts('Server connected'); }, verifyClient: true, verify: function(c, verified, depth, certs) { sys.puts( 'Server verifying certificate w/CN: \"' + certs[0].subject.getField('CN').value + '\", verified: ' + verified + '...'); // accept any certificate (could actually do WebID authorization from // here within the protocol) return true; }, getCertificate: function(c, hint) { sys.puts('Server getting certificate for \"' + hint[0] + '\"...'); return data.server.cert; }, getPrivateKey: function(c, cert) { return data.server.privateKey; }, tlsDataReady: function(c) { // send base64-encoded TLS data over websocket websocket.write(forge.util.encode64(c.tlsData.getBytes())); }, dataReady: function(c) { sys.puts('Server received \"' + c.data.getBytes() + '\"'); // send response c.prepare('Hello Client'); }, closed: function(c) { sys.puts('Server disconnected.'); websocket.end(); }, error: function(c, error) { sys.puts('Server error: ' + error.message); } }); }; // create websocket server var port = 8080; ws.createServer(function(websocket) { // create TLS server connection var tls = createTls(websocket); websocket.addListener('connect', function(resource) { sys.puts('connected: ' + resource); // close connection after 10 seconds setTimeout(websocket.end, 10 * 1000); }); websocket.addListener('data', function(data) { // base64-decode data and process it tls.process(forge.util.decode64(data)); }); websocket.addListener('close', function() { sys.puts('closed'); }); }).listen(port); sys.puts('server running on port ' + port);