admin管理员组

文章数量:1391987

I have a central web-server (Node.js) and also have several client machines (also running Node). These clients are going to be pushing data into the web-server and so, for security, the clients will initially register with the main server - generate it's own unique SSL private/public keys and store the public key on the server.

Now, after the registration, every time a client tries to municate with the server, it needs to present it's Public key(?) to authenticate itself.

I am trying to understand how to go about this. Should I store the contents of all the public keys of the clients in a regular database collection?

How do I actually make the clients "present" their certificates along with their data? I've seen a few packages like client-certificate-auth but I don't think this will help me for my use-case.

EDIT: I forgot to mention, I will be municating over HTTPS (port 443) so I think that takes care of the actual security part. I just want to make sure that no rogue, unregistered client pushes data into the server using pub/private encryption / SSL certs.

I have a central web-server (Node.js) and also have several client machines (also running Node). These clients are going to be pushing data into the web-server and so, for security, the clients will initially register with the main server - generate it's own unique SSL private/public keys and store the public key on the server.

Now, after the registration, every time a client tries to municate with the server, it needs to present it's Public key(?) to authenticate itself.

I am trying to understand how to go about this. Should I store the contents of all the public keys of the clients in a regular database collection?

How do I actually make the clients "present" their certificates along with their data? I've seen a few packages like client-certificate-auth but I don't think this will help me for my use-case.

EDIT: I forgot to mention, I will be municating over HTTPS (port 443) so I think that takes care of the actual security part. I just want to make sure that no rogue, unregistered client pushes data into the server using pub/private encryption / SSL certs.

Share Improve this question edited Sep 29, 2016 at 15:38 Ayrton Senna asked Sep 29, 2016 at 3:11 Ayrton SennaAyrton Senna 3,8656 gold badges35 silver badges54 bronze badges 2
  • Are you planning on using the subtle web crypto API? I think I understand what you're wanting. I can write an example for you... You want the private keys generated in javascript kept secret at the clients, and a public key sent and stored securely on the server... – TylerY86 Commented Sep 29, 2016 at 3:51
  • 1 During authentication, the client says what it's public key is by a unique identifier token. The server then issues a challenge with a message payload encrypted with the user's public key. The user decrypts the message with his private key, and then responds correctly. This provides no security, you will have to perform this over an already established SSL connection. It is an alternative to the traditional cookie and session token, and it's just different, harder, and not better. The private key never arrives at the server at any time. – TylerY86 Commented Sep 29, 2016 at 3:53
Add a ment  | 

2 Answers 2

Reset to default 4

If you're going down this path, use the Subtle Crypto API. Most likely, you shouldn't be doing this.

You want the private keys generated in javascript kept secret at the clients, and a public key sent and stored securely on the server.

During authentication, the client says what it's public key is by some unique identifier associated with it's public key, e.g. id or mon name or user name.

The server then issues a challenge with a message payload encrypted with the client's public key.

The user decrypts the message with his private key, and then responds with the correct decrypted response.

This provides no security, you will have to perform this over an already established SSL connection.

It is an alternative to the traditional cookie and session token, and it's just different, harder, and not better.

The private key never arrives at the server at any time. The client does not encrypt using it's private key, that's not how public-key cryptography works.

It can however send a digital signature, and the server can verify that. That is an alternative to a unique identifier; make sure you specify a true and sufficiently long nonce to sign though.

To perform a digital signature challenge, the server sends a challenge string to the client, the client signs the challenge using it's private key and responds to the server, the server then verifies the signature using the public key. The public key must be part of the signature, and the server will have to know to trust the public key, so it'll have to have a way to look it up quickly.

Another alternative is to rely on the knowledge of the user in setting up their own client certificates, in which case passport-client-cert as mentioned in Paul's answer can handle that.

I'd strongly remend not doing this yourself, there are a lot of things you can get wrong if you don't implement it correctly.

That said, the way this kind of thing works architecturally is not to "present the client's public key" but instead to have the client encrypt something with its private key and send that encrypted data to the server, which then decrypts with the client's public key. If it's able to do that, it knows the client is the client it claims to be (in theory; the reliability of this can vary depending on your keyspace).

What does the client encrypt? Well, that depends a lot on (again) how secure you want to be / paranoid you are. One way to do this (quasi-kerberos) would be for the client to send a request to the server for the information to encrypt. This is done over SSL, so the client can ensure that the server is who it says it is (and can check a CA and such if it wants). That thing passed back is some data that includes a random value, an expiry, and possibly a nonce of some kind. It's also stored by the server for lookup later verification and of course evicted on time. The client would typically take that exact object (possibly a JSON object) and encrypt it with its private key and send it back to the server to some login endpoint. As I said before, the server would then check its storage location for that object based on the client's ID, and do the parison to see if the two objects are identical. If they are, then it can accept the client is who it says it is.

Normally, this handshake is done only to exchange a session key that the client can use to encrypt all its traffic, since a symmetric key encryption is typically easier on the CPU than PKI.

Honestly, though, I've only scratched the surface. You're probably much better off looking at what PassportJS has to offer for strategies and picking one of those. Perhaps passport-api-key or passport-client-cert will do what you need.

本文标签: