Using ECDSA to sign a ECDiffieHellman-derived key Assuming that Alice and Bob know the hash of each other's public key, take this method:


Use ECDiffieHellman with temporary private keys each time to generate a per-session shared symmetric key
Create an AES connection secured with the shared key (unique IVs for each message, verified with HMAC)
Send their public keys along with their signatures of that particular session key over the encrypted connection to authenticate each other (by verifying that the public key matches the stored hash, and that the signature was signed by the public key).


Is this a safe way to create a secure and authenticated session? Are there any better ways that do not require pre-existing knowledge of the private key (or trust in a centralised certificate authority). I know that you should always try to use standard libraries, but I am interested in understanding more about cryptography - this will not be used in any critical software.

Thanks very much for your help.
Sure, first you set up a 1:1 communication and then you establish trust in it. This is kinda like TLS 1.3 where encryption starts as soon as possible. Of course, anything up to the authentication of the entity and handshake can be generated by an adversary, so it is slightly dangerous in that sense.

And in general, you would try and authenticate as many handshake parameters as possible, rather than just the ongoing channel. Basically you try and tend to achieve confidentiality and authentication over as much data as possible. You could do that by hashing all the communication messages and then signing that separate hash, for instance.

As for the trust in the public keys: yeah, sure. This is almost identical to certificate pinning after all, where a certificate is trusted explicitly rather than just a public key. The advantage of using a certificate is of course that you can use a certificate chain later and that a certificate contains more information than just a public key (validity period, identification information, CRL and whatnot). So generally if you want to use a public key, why not create a self signed certificate for it and pin that instead.

The described scheme can certainly be part of a secure protocol. If the protocol is actually secure depends on a lot of other factors. And such details matter even for the specific scheme mentioned (parameter validation, side channel resistance, avoidance of replay attacks and mirror or reflection attacks), and so on. Creating a secure transport protocol is one of the most daunting tasks, especially for a beginner.