WristMan
WristMan

Reputation: 347

Node TLS socket : DEPTH_ZERO_SELF_SIGNED_CERT error

I am trying to setup a server and some clients using TLS in node. I am using self-signed certificates on the clients and the server. The server runs ok, but when I try to connect a client I end up with the following error on the client side:

Error: DEPTH_ZERO_SELF_SIGNED_CERT

Cert Generation

CA cert:

    # Create key to sign our own certs. Act like as our own a CA.
    echo "SecuresPassphrase" > ./tls/passphrase.txt
    openssl ecparam -name secp521r1 -genkey -noout -out ./tls/certs/ca/ca.plain.key # Generate private key
    openssl pkcs8 -topk8 -passout file:./tls/passphrase.txt -in ./tls/certs/ca/ca.plain.key -out ./tls/certs/ca/ca.key   # Generate encrypted private key
    rm ./tls/certs/ca/ca.plain.key; # Remove unencrypted private key
    # Generate CA cert
    openssl req -config ./openssl/oid_file -passin file:./tls/passphrase.txt -new -x509 -days 365 -key ./tls/certs/ca/ca.key -out ./tls/certs/ca/ca.crt

Server Cert:

    openssl ecparam -name secp521r1 -genkey -noout -out ./tls/certs/servers/server.key # Generate server private key
    openssl req -config ./openssl/oid_file -new -key ./tls/certs/servers/server.key -out ./tls/certs/servers/server.csr # Generate signing request
    openssl x509 -passin file:./tls/passphrase.txt -req -days 365 -in ./tls/certs/servers/server.csr -CA ./tls/certs/ca/ca.crt -CAkey ./tls/certs/ca/ca.key -CAcreateserial -out ./tls/server.crt
    mv ./tls/server.crt ./tls/certs/servers/

Client cert:

Client's certs are created inside a bash loop, the variable ${name} contains the name of the client and changes each iteration.

    openssl ecparam -name secp521r1 -genkey -noout -out ./tls/certs/clients/${name}/client.key
    openssl req -config ./openssl/oid_file -new -key ./tls/certs/clients/${name}/client.key -out ./tls/certs/clients/${name}/client.csr
    openssl x509 -passin file:./tls/passphrase.txt -req -days 365 -in ./tls/certs/clients/${name}/client.csr -CA ./tls/certs/ca/ca.crt -CAkey ./tls/certs/ca/ca.key -CAcreateserial -out ./tls/client.crt
    mv ./tls/client.crt ./tls/certs/clients/${name}/

I am also trying to use Perfect Forward Secrecy by using ephemereal Diffie-Hellman interchange. The parameters, for clients and server, are created as openssl dhparam -outform PEM -out ./tls/params/servers/server/dhparams.pem 2048

Server's code:

return new Promise(resolve => {
            // Define parameters of TLS socket
            const options = {
                rejectUnauthorized: false,  
                requestCert: true,
                // Secure Context Parameters
                ca: [fs.readFileSync("tls/certs/ca/ca.crt")], 
                cert: fs.readFileSync("tls/certs/servers/server.crt"),
                key: fs.readFileSync("tls/certs/servers/server.key"),
                ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:!RC4:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!SRP:!CAMELLIA",
                dhparam: fs.readFileSync("tls/params/servers/server/dhparams.pem"),
                ecdhCurve: tls.DEFAULT_ECDH_CURVE,
                minVersion: "TLSv1.2"
            };
            // Iniciar servidor TLS
            this.SERVIDOR = tls.createServer(options, function (socket) {
                console.log("Server created."); 
            });

            this.SERVIDOR.listen(this.puerto, this.direccion, function () {
                console.log("Listening");
            });

            this.SERVIDOR.on("secureConnection", (socket) => this.handleRequest(socket));

            this.SERVIDOR.on("tlsClientError", (error) => console.log("Error client TLs. %s", error));
        });

Client's code:

return new Promise(resolve => {
            // Define parameters of TLS socket
            const options = {
                host: this.NODE,
                port: this.NODE_PORT,
                rejectUnauthorized: false,
                secureContext: tls.createSecureContext({
                    ca: [fs.readFileSync("tls/certs/ca/ca.crt")],
                    cert: fs.readFileSync("tls/certs/clients/" + this.NAME + "/client.crt"),
                    key: fs.readFileSync("tls/certs/clients/" + this.NAME + "/client.key"),
                    ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:!RC4:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!SRP:!CAMELLIA",
                    dhparam: fs.readFileSync("tls/params/clients/" + this.NAME + "/dhparams.pem"),
                    ecdhCurve: tls.DEFAULT_ECDH_CURVE, 
                    minVersion: "TLSv1.2"
                })
            };
            // Initialize TLS socket
            this.WEB_SOCKET = tls.connect(options, function () {
                // Check if TLS auth worked
                if (this.authorized) {
                    console.log("Connection authorized by a Cert. Authority ");
                } else {
                    console.log("Authorization not granted. Error: " + this.authorizationError);
                }
            });

What I have tried:

¿Am I wrongly generating the certs? Any help is appreciated. Thanks!

EDIT. 16/10/2019 There was a problem in the code, I didn't use resolve(); when the sockets were up. The same problem remains... BUT despite of getting an authorization error on the client, the server fires up the "secureConnection" event and messages are interchanged. ¿Does this makes sense? *Yes, it makes sense since the server accepts unauthorized connections. If I set the server to reject not certified connections the clients hung up *

Upvotes: 1

Views: 5898

Answers (1)

WristMan
WristMan

Reputation: 347

The problem was I was using the same configuration file (./openssl/oid_file) for all the certificates. Using different configuration files and different Alternative names solved this issue.

I ended with an "UNABLE_TO_VERIFY_LEAF_SIGNATURE" error. The certificates were properly generated but it didn't work. I couldn't find a working example of self-signed certificates in nodejs. Most of them simply deprecated the use of certificates by disabling SSL or accepting unathorized transactions, which is the opposite of what TLS is supposed to do.

Finally, I used this tool to generate the certificates: https://github.com/FiloSottile/mkcert . The best and simplest way to generate self-signed certificates in a testing environment. You only need to set the node variable NODE_EXTRA_CA_CERTS to point the root certificate:

process.env.NODE_EXTRA_CA_CERTS = [os.homedir() + "/.local/share/mkcert/rootCA.pem"];

-

Upvotes: 3

Related Questions