0

I'm writing a module that creates a secure communication channel using ZeroMQ sockets and Pycryptodome.

The initial handshake between client and server would follow these steps :

  1. Both parties send their public RSA key to each other.
  2. The server generates an AES session key and a signature for that key.
  3. The server RSA-encrypts the session key and the signature before sending it to the client. (*)
  4. The client verifies the signature and stores the session key.
  5. The client generates a token, generates its signature and sends both AES-encrypted to the server.
  6. The server verifies the signature and echoes back the token.
  7. If the token received matches the one sent, the handshake is considered successful.

I found on this thread that it was preferable to sign the message then encrypt it, rather than encrypting then signing it.

The problem is that the signature, for a 2048 bits RSA key, is 256 bytes long. The maximum encryption size for the same key is 190 bytes. This means I can't encrypt the signature as suggested in the thread.

Should I encrypt the signature with the AES session key ? Should I proceed another way ?

I know there are "standardized" key exchange protocols (ECDH for example) but they are not available in Pycryptodome yet.

Cipher: RSA PKCS1 OAEP
Signing : PKCS1 PSS w/ BLAKE2b hash
Rémi Héneault
  • 383
  • 3
  • 12
  • 1
    There is a huge problem with your scheme: you need to *trust* the public keys; you cannot just send them. Transport protocols are a different kettle of fish than message signing. It is perfectly possible to encrypt-then-sign in a well designed protocol. Generally I'd say you could simply AES encrypt with a random AES key and then encrypt the AES key (hybrid encryption to get hybrid encryption, yay), but I think there are other things wrong in this scheme; transport protocols are notoriously hard to get right. Hence the most likely response remains: use TLS. – Maarten Bodewes Feb 07 '19 at 14:35
  • You mean that the two parties should acquire the other's party public key via a secure and authenticated channel beforehand to ensure that "they are talking to the person they want" ? – Rémi Héneault Feb 07 '19 at 14:53
  • Yes, otherwise you have active attacks where an adversary simply replaces the public key with one of his own (MitM attack, for instance). Of course, this is why there is normally a distinction between static authentication key pairs (for which the public key must be trusted) and ephemeral key agreement key pairs. – Maarten Bodewes Feb 07 '19 at 14:59
  • I posted the complete handshake procedure. Wouldn't the server's verification of the client signature prevent such attacks ? Looking to it i don't think so... An attacker could generate a signature with his private key that would match the public key he sent. – Rémi Héneault Feb 07 '19 at 15:09
  • Only if the public key of the client can be trusted, otherwise you may be verifying with the public key of the adversary. Your step 1 - exchanging the public keys - is written as part of the protocol, which means to me that it is not part of some out-of-band procedure with steps in place to trust the public keys. – Maarten Bodewes Feb 07 '19 at 15:24
  • Indeed it is not. I could implement a password verification, that both parties should know beforehand, and that each would send to the other HMAC-hashed ? – Rémi Héneault Feb 07 '19 at 15:38
  • 1
    Read about "pre-shared secret" or PSK. This is becoming more and more a "how to design a transport protocol" territory though :) I'm afraid we need a couple of pages more to get anywhere. I'll just type two things more: `TLS_PSK_WITH_AES_256_CBC_SHA` and `TLS_RSA_WITH_AES_256_CBC_SHA256` . Good luck... – Maarten Bodewes Feb 07 '19 at 16:02
  • BLAKE is very cool for hashing a lot of data. I would not use it in a signature used for authentication purposes though. I'd go for compatibility and therefore SHA-256 or SHA-512. Beware of compatibility issues with the hash used for MGF1 in PSS. – Maarten Bodewes Feb 07 '19 at 16:09

0 Answers0