My goal is to allow two clients to send files securely over an untrusted network without the need for more than one block of information to be sent. Both clients have ECDSA keys of size 256 bits. I'd like to stress that this is purely for fun and to learn elliptic curve concepts. This will not be used in a serious environment. That being said, here's the protocol design:
Generate a random ECIES value using a random private number and the reciever's public key. Call the resulting key "Key" and the public ECIES value "ECIESPub".
Calculate the sha256 hash of "Key + filecontents" where + is concatenation and sign it with your ECDSA key. Call the result "Sig".
Encrypt the file contents with Key using AES-256-CFB. Call the result "Encrypted" and the IV of the algorithm "IV".
Create a new file with the original file name with ".enc" appended. (dual extensions is acceptable) Write "ECDSAPublicKey + ECIESPub + IV + Encrypted + Sig".
Send this file to the recipient. eg. through skype or email.
On the reciever's end:
Calculate "Key" using "ECIESPub" and your own private ECDSA key.
Decrypt "Encrypted" with "Key" and "IV". Write the result to a new file with the filename of the received file with ".enc" simply removed.
Calculate the sha256 hash of "Key + DecryptedFileContents" and verify it with "Sig" and the sender's ECDSA public key.
If the signature is valid, display a fingerprint derived from the sender's public key for the reciever to compare with their record of fingerprints. If the signature is not valid, display a warning to the reciever. In neither case will the sender gain any information about the success or failure of verification.
Note: I include the key in the generation of the signature to prevent an attack where an attacker can switch out the public key and signature with their own without changing or knowing the secret shared key, on the condition that they know the plaintext. I don't know how practical this attack is, but I thought it was best to combat it.
Are there any glaring holes in this construction that I'm missing?
Quick edit: I realize I'm reusing a key for signing and encryption, however, the main concern about this is the occasional legal requirement to give up an encryption key. If that happens, the reciever can recalculate the key from the public ECIES value and give that up instead. The sender, however, simply won't have the key anymore as it is randomly generated, used once, then forgotten.
Hash(key | data)
. I see possible padding oracle attacks on the unauthenticated ciphertext. Even if the code could be secure, it doesn't seem to follow established practices. $\endgroup$