Public key and TLS ? #1472

Closed
Dededede4 opened this Issue Aug 7, 2011 · 17 comments

Projects

None yet

4 participants

@Dededede4

Hello, and sorry for my bad English.
I can not find the API documentation of the TLS module which retrieves the public key of the client that connects to my server.

You have an idea?
Thank you!

@bnoordhuis
Member

I believe stream.getPeerCertificate() is what you want. It's not documented right now but that's true for a lot of other crypto functions.

@koichik: can you maybe add documentation?

@koichik
koichik commented Aug 8, 2011

okay, I will write it.

@Dededede4

I'm using Node v0.4.10 and getPeerCertificate does not work (or I do not have the necessary knowledge to use it.)

tls.createServer(options, function (s) {
    s.setEncoding('utf8');

    var test = s.getPeerCertificate();
    console.log(test); // It say "{}"
    console.log(test.issuer); // undefined
    s.pipe(s);
}).listen(port);

getPeerCertificate is empty ?!

@nponeccop

What type of client you use? Browsers by default don't use any certificates, so double check that the client is configured to authenticate itself using a certificate.

@Dededede4

I simply use openssl s_client -connect 127.0.0.1 .

But I'm not interested by the certificate, I simply want the public key used by the client.

@Dededede4 Dededede4 closed this Aug 10, 2011
@Dededede4 Dededede4 reopened this Aug 10, 2011
@koichik
koichik commented Aug 10, 2011

Did you set options.requestCert = true?
http://nodejs.org/docs/v0.4.10/api/tls.html#tls.createServer

@Dededede4

var options = {
key: fs.readFileSync('./clefs/server-key.pem'),
cert: fs.readFileSync('./clefs/server-cert.pem'),
requestCert : true
};

And is returns the same thing as before.

@koichik
koichik commented Aug 10, 2011

If you use self-signed certificate on your client, you should set options.ca.

var tls = require('tls'), fs = require('fs');
var options = {
  key: fs.readFileSync('server-key.pem'),
  cert: fs.readFileSync('server-cert.pem'),
  ca: [fs.readFileSync('client-cert.pem')],
  requestCert: true
};
tls.createServer(options, function (socket) {
  console.log(socket.getPeerCertificate());
  socket.end('Hello, World!');
}).listen(8124, '127.0.0.1');
$ openssl s_client -connect 127.0.0.1:8124 -key client-key.pem -cert client-cert.pem

result:

{ subject: 
   { C: 'JP',
     ST: 'Kanagawa',
     O: 'node',
     OU: 'client',
     CN: 'http-client',
     emailAddress: 'client@example.com' },
  issuer: 
   { C: 'JP',
     ST: 'Kanagawa',
     O: 'node',
     OU: 'client',
     CN: 'http-client',
     emailAddress: 'client@example.com' },
  valid_from: 'Aug 10 10:42:25 2011 GMT',
  valid_to: 'Aug  7 10:42:25 2021 GMT',
  fingerprint: '56:FF:90:FB:46:9D:5A:AC:9F:3B:7C:76:C1:C4:A9:FC:6E:FD:EA:2A' }
@nponeccop

But I'm not interested by the certificate, I simply want the public key used by the client.

Which public key? In case of openssl s_client -connect 127.0.0.1 generated diffie-hellman or RSA public key is random and is of no use. If you want to use a keypair and not a full X.509 certificate, you should pass them to s_connect (see -key client-key.pem -cert client-cert.pem above). Without -key and -cert openssl s_connect generates a temporary keypair which cannot be used to identify client.

@Dededede4

@nponeccop I use this command only for my tests.
For my project, the public keys of the client (or only fingerprint) will use.
I will use a static key for each client.

@koichik It is not possible to find the fingerprint of the public key of the customer without going through the system of trusted certificates ?

@nponeccop

It is possible to use just key pairs without a public key infrastructure. But every client has to generate and use a non-temporary key pair.

@Dededede4

That's what I want to do.
But I still can not retrieve the fingerprint of the client with a node.js without the help of trusted certificates, the way to koichik.

If you don't understand me, keep me informed.

@nponeccop

Koichik used "non-trusted" (self-signed) certificates. Will that work for you?

@koichik koichik added a commit to koichik/node that referenced this issue Aug 11, 2011
@koichik koichik Doc improvements
related to #1472.
d30251c
@koichik
koichik commented Aug 11, 2011

@bnoordhuis - Please review d30251c.

@koichik koichik added a commit that referenced this issue Aug 11, 2011
@koichik koichik Doc improvements
related to #1472.
d1a2628
@Dededede4

Thank you for your help.

@Dededede4 Dededede4 closed this Aug 13, 2011
@Dededede4

I'm sorry for the UP, but I have this problem again ... the other way!
Indeed, I can not take the fingerprint of the server where I try to connect:

_CONFIG.certs = {
  key: fs.readFileSync('./clefs/Clef-privee.key'),
  cert: fs.readFileSync('./clefs/certification-Serveur.key'),
  ca: fs.readFileSync('./clefs/certification-de-autorite.key'),
  requestCert: true
};
var port = 4628;

tls.createServer(_CONFIG.certs, function (s) {
    console.log(s.getPeerCertificate().fingerprint); // It OK
    tls.connect(port, 'localhost', _CONFIG.certs, function (s2) {
            console.log(s2.getPeerCertificate); // Undefined
        });
}).listen(port);
@Dededede4 Dededede4 reopened this Aug 24, 2011
@koichik
koichik commented Aug 24, 2011

Please try this:

_CONFIG.certs = {
  key: fs.readFileSync('./clefs/Clef-privee.key'),
  cert: fs.readFileSync('./clefs/certification-Serveur.key'),
  ca: fs.readFileSync('./clefs/certification-de-autorite.key'),
  requestCert: true
};
var port = 4628;

tls.createServer(_CONFIG.certs, function (s) {
    console.log(s.getPeerCertificate().fingerprint); // It OK
}).listen(port, function() {
    var s2 = tls.connect(port, 'localhost', // return value!
                         _CONFIG.certs, function() { // no arg!
        console.log(s2.getPeerCertificate().fingerprint);
    });
});
@Dededede4 Dededede4 closed this Aug 25, 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment