10. Updating the threat model
November 20, 2017 ยท View on GitHub
By now our bank has mitigated the original threat model to a degree where the threat has shifted from the transaction log itself, and unto the key-pair. This means that we have centralised security onto something that is easier to reason about and has a much smaller attack surface, albeit being even more sensitive to the operation of our bank. However, this problem is now more a question of operations and policy than cryptography.
This also means that our priorities shift as we now have other threats that pose higher risk. In this age of data leaks, we want to make sure that if an adversary, eg. a three letter gov't agency, breaks into our bank server at night and steals the transaction log, they stand to learn very little about the banks business.
To achieve this, we need to introduce a new cryptographic primitive, symmetric encryption.
Symmetric crypto dates all the way back to at least Julius Caesar, who used it
to communicate securely with his generals. Much has happened since then, but the
basic idea is the same, you have a key that is used for both the encrypt and
decrypt operations. In modern schemes you often also need a nonce which is
often a random piece of data, that is not required to be secret, but protects
against a several classes of attacks.
Using sodium-native this functionality is exposed through the
crypto_secretbox APIs:
sodium.crypto_secretbox_easy(cipher, message, nonce, secretKey)EncryptmessageBufferintocipherBufferwithnonceandsecretKey. The secret key must besodium.crypto_secretbox_KEYBYTESand is best generated using thesodium.randombytes_bufAPI. This key must be persisted somehow.nonceshould be another random buffer of sizesodium.crypto_secretbox_NONCEBYTES. ThecipherBuffershould bemessage.length + sodium.crypto_secretbox_MACBYTESlong. It is important that you never re-use a nonce to encrypt more than a single message.var bool = sodium.crypto_secretbox_open_easy(message, cipher, nonce, secretKey)DecryptcipherBufferintomessageBufferusingnonceandsecretKey. Will return abooleandepending on whether the cipher text could be decrypted.
Problem
Use the APIs described above to make three new programs, secret-key.js
encrypt.js and decrypt.js.
secret-key.jsshould generate a secret key using therandombytes_bufapi of the correct lengthencrypt.jsshould accept a secret key and a message and print out the encrypted message and the random nonce used to encrypt it.decrypt.jsshould accept the encrypted message, secret key and nonce and print out the plaintext message if valid.
Testing
Try running a couple of test messages like Hello, World through your encrypter
and try decrypting them to see that it works. Then try tampering with some of
the encrypted messages to see that decryption fails.