I'm working on a cryptography-related project, which uses ECC (elliptic curve cryptography). And one of the things that I need is a "secure" communication channel for two entities.
I need someone to review the design. 1. First step is establishing a "shared secret". This is done in terms of Diffie-Hellman protocol. However I've read that it's not a good practice to use the "master" key for this. Because once it's compromised - all the past and future communication history of this entity is compromised as well.
So, A and B both generate nonces (scalars), and exchange the public nonces (i.e. points, G * nonce). Each multiplies its private scalar by peer's point, and they come up with the same point. Its x-coordinate is the shared secret.
2. For traffic encryption I use the AES-256 symmetric encryption in a CTR mode, as a stream cipher. The shared secret is hashed (via SHA-256), this is the symmetric key. Then it's hashed again, and this gives the IV (which is, in case of CTR, is the initial value of the "counter").
I know that the weakness of the CTR stream cipher is that anyone can easily modify the encrypted message (flip bits), and a sort of HMAC is needed. However I'd like to keep the overhead is small as I can. For this I attach a CRC-32 checksum of the message with the message counter, which is increased after every message sent. That is:
CipherMessage = AES-Stream-Cipher XOR (PlainMessage | CRC32(PlainMessage | MsgCounter++))
The initial value of MsgCounter
is secret as well (derive from the shared secret)
3. After secure channel is established both entities prove their identities. This is done in terms of Schnorr's signature. Both send their public keys (points) with the Schnorr's signature. The signed message is the peer's public nonce. This scheme both proves the ownership of the public key, and prevents the man-in-the-middle attack (since we are signing the public nonce, which was used in establishing the secure channel for those specific entities).
4. One minor point: for all the "public" keys and nonces, which assume an elliptic-curve points, we actually transfer only the X-coordinate. The peer always selects the appropriate Y-coordinate in an unambiguous way (for example, assuming it must be even), and the private scalars are always selected appropriately (if they eventually correspond to a point with inappropriate Y-coordinate - they are just negated).
So, my question is, is this design secure enought? I understand that CRC-32 doesn't sound secure, brute-forcing 32 bits is relatively easy. But in my case this is only used in "live" communication, and whenever error in protocol is detected, the peer is banned for a substantial time.
Thanks in advance