You have a Node.js server that is transmitting information and you want to ensure the security of that transmission by utilizing Node.js’s TLS module.
Solution
Building a TLS server in Node.js will look familiar. It is similar to the HTTPS server that you created in Chapter 4. This is because the underlying architecture of the HTTP server object is inherited from the TLS module.
To create a TLS server you need to start with the TLS module itself. Then you will build a reference to your server key and certificate files and pass them as options, as shown in Listing 6-14.
Chapter 6 ■ ImplementIng SeCurIty and Cryptography
Listing 6-14. Create a TLS Server /** * using TLS */ var tls = require('tls'), fs = require('fs'); var options = { key: fs.readFileSync('srv-key.pem'), cert: fs.readFileSync('srv-cert.pem') }; tls.createServer(options, function(s) { s.write('yo'); s.pipe(s); }).listen(8888);
Once you have created your secure TLS server with a valid key and certificate, you need to create a client that is capable of connecting to it. This is a capability of Node.js as well. In fact, as Listing 6-15 shows, it is nearly identical to the net module’s ability to create a connection; however, you need to be mindful to point to the certificate authority and credentialing for the secure transport to be authenticated.
Listing 6-15. TLS Connection /** * tls connection */ var tls = require('tls'), fs = require('fs'); var options = { key: fs.readFileSync('privatekey.pem'), cert: fs.readFileSync('certificate.pem'), ca: fs.readFileSync('srv-cert.pem') };
var connection = tls.connect(8888, options, function() { if (connection.authorized) {
console.log('authorized'); } else {
console.log(':( not authorized'); }
});
connection.on('data', function(data) { console.log(data);
Chapter 6 ■ ImplementIng SeCurIty and Cryptography
How It Works
TLS is a way to encrypt data that are sent to and from a server. In this solution you created a server that utilized a key and certification, generated via OpenSSL commands in the terminal just as you saw in Chapter 4.
Listing 6-16. Generating OpenSSL Keys $ openssl genrsa -out srv-key.pem 1024
$ openssl req -new –key srv-key.pem -out src-crt-request.csr
$ openssl x509 -req -in srv-crt-request.csr -signkey srv-key.pem -out srv-cert.pem
Once you have the key and the certificate, you pass these into the options object when you call tls.createServer and tell it to listen on port 8888. The createServer function takes not only the options argument but also a callback. This callback is emitted on a connection to the server and passes along the secure stream with the function. In your solution, you write a string to the stream and then pipe that out.
There are many more options that are available when you create a server, such as setting a timeout for the handshake or rejecting unauthorized connections. All of these are taken into account to secure your server.
• ca: An array of strings or buffers of trusted certificates.
• cert: A string or buffer containing the certificate key of the server in Privacy Enhanced Mail (PEM) format. (Required)
• ciphers: A string describing the ciphers to use or exclude.
• crl : A string or list of strings of PEM-encoded certificate revocation lists (CRLs)
• handshakeTimeout: Aborts the connection if the SSL/TLS handshake does not finish in a certain number of milliseconds. The default is 120 seconds.
• honorCipherOrder: When choosing a cipher, uses the server's preferences instead of the client preferences.
• key: A string or buffer containing the private key of the server in PEM format. (Required) • NPNProtocols: An array or buffer of possible Next Protocol Negotiation (NPN) protocols.
(Protocols should be ordered by their priority.)
• passphrase: A string or passphrase for the private key (or pfx).
• pfx: A string or buffer containing the private key, certificate, and certificate authority (CA) certificates of the server in PFX (or PKCS #12) format. (This is mutually exclusive with the key, cert, and ca options.)
• rejectUnauthorized: If true, the server will reject any connection that is not authorized with the list of supplied CAs. (This option only has an effect if the requestCert is true; the default is false.)
• requestCert: If true, the server will request a certificate from clients that connect and will attempt to verify that certificate. (The default is false.)
• sessionIdContext: A string containing an opaque identifier for session resumption. • SNICallback: A function that will be called if the client supports the Server Name
Identification (SNI) TLS extension.
It is interesting to note that these values become part of the credentials that are created to identify your server. This is done by passing the relevant parameters into the crypto.createCredentials function.
Chapter 6 ■ ImplementIng SeCurIty and Cryptography
Listing 6-17. createServer Methos Credentials var sharedCreds = crypto.createCredentials({ pfx: self.pfx,
key: self.key,
passphrase: self.passphrase, cert: self.cert,
ca: self.ca,
ciphers: self.ciphers || DEFAULT_CIPHERS, secureProtocol: self.secureProtocol, secureOptions: self.secureOptions, crl: self.crl,
sessionIdContext: self.sessionIdContext });
Now you have a secure TLS server. You need to connect to it. To test the connection, simply open a terminal window and connect.
Note
■
on Windows, openSSl is not included by default. you can easily add it to your machine by downloading a binary
at
http://openssl.org/related/binaries.html. this will install to C:\openSSl-Win32 on your machine. you can then
run openSSl from powerShell from within the C:\openSSl-Win32\bin directory.
Listing 6-18. Connecting to a Secure Server $ openssl s_client –connect localhost:8888
However, a more robust client, such as one built with Node.js, is possible. To build your client connection in your solution, you first create a connection with tls.connect. To this you pass the port (and optionally a URL). Then there is the options object, which you will notice looks quite similar to the options of the server, with the exception of the ‘ca’ option. This is the value of the CA of your server. Because the credentials for your server were self-signed, the only way to identify it is through itself. Once you have connected, you have access to the connection stream. This stream has a property that will tell you if you are actually authenticated to the server or not. From there, once you are authorized, you can perform the client-server interactions that you normally might in a networked application, but you now have the added security of TLS.