Currently, I am creating a project with an IoT device. This is an offline device which shows a QR code which can be scanned by a mobile device, which sends this code to a server. The server handles data but does not send anything back.
The plaintext data part of the QR code needs to be encrypted and should not be changed, nor intercepted, so I made the following protocol:
- The IoT device generates a new EC keypair at every boot;
- The server has a permanent EC keypair. The server public key is stored in the firmware of the IoT device;
- When creating a QR-code, the IoT device calculates a DH agreement with the server's public key and the private key of the IoT device;
- The IoT device creates an IV from an incremented nonce (8 bytes array);
- The data gets encrypted using chacha20 with the calculated agreement;
The QR code is then generated using the following format:
(IoT public key) + (iv) + (ciphertext).
The server is then able to decrypt the ciphertext by using the IoT public key, which can be used for calculating the agreement and the IV for decrypting the ciphertext.
Now I have several concerns since I am new to crypto and I am almost sure that my protocol is not safe enough.
- Is it safe to embed and send the IV in plain text in every QR-code?
- When using the same nonce, decryption will still work, what is the purpose or misuse of the nonce here?
- Should I use chacha20 at all? Or is there a much better encryption/decryption method to use here?
- I need to keep my server's public key secret and only in the firmware of the IoT device, to prevent 'fake devices' generating valid but fake QR codes, which sounds bad.