Closed patolax closed 5 years ago
Hello @tpatikirikorala,
The lazy version of the api does not provide an interface to encrypt a byte array (AsymmetricEncryptionActivity sample code). I want to convert a bitmap image to a byte array as below and encrypt it. How can I achieve this?
This section in the libsodium docs is a great resource. By the looks of it, using the SecretStream related functions is the way forward.
Another option is converting the image to base64, then encrypting the resulting string.
Also from my reading, I noticed that nonce should be generated by the messaging protocol so that it does not have to be transferred over the internet. Do you know a sample source code for a chat application which generates nonce so that chat users can encrypt and decrypt messages without tranfering nonce with the message?
You must use a random nonce when sending an encrypted message from participant A
to participant B
. Please refer to this SO answer, answered by the creator of libsodium himself. Rewriting here for posterity:
A unique nonce is required for every message sent using a given shared secret key. The nonce doesn't have to be secret; a simple counter is totally fine; changing a single bit in the nonce is going to make the ciphertext look totally different even if the same message is sent twice.
What's a shared secret? It a key calculated from (A's secret key, B's public key) or (A's public key, B's secret key). A and B perform a different calculation, based on what they have, but end up with the same shared secret.
The shared secrets used in crypto_box are 256-bit long. Which is huge. You can safely consider that shared secrets are going to be unique for each "conversation".
So, (A, B), (A, C) and (C, B) can safely exchange messages using the same nonces. But if A sends a message to B using a given nonce, B cannot send a message to A using the same nonce. Nonces have to be unique for everything exchanged during a conversation between A and B.
So, a simple counter can be fine. Have A pick even numbers, leave odd numbers to B, increment the nonce by 2 after every message sent and you're good to go.
But the cipher used in the crypto_box construction actually has a really huge nonce. 192 bits.
Which means that if you ignore everything I wrote and just pick a random nonce every time you send a message, the probability to get a collision is so small that you can rest assured that it will never ever happen in practice.
Some stream ciphers included in Sodium (AES128-CTR, ChaCha20, Salsa20) have a shorter nonce, and require a counter to avoid collisions. This is why they are in the "advanced" section of the documentation.
But with crypto_box and crypto_secretbox, just pick a random nonce every time (randombytes_buf(nonce, sizeof nonce)) and you will be safe.
What I am confused about is when A sends a message to B with nonce X, how does B know about X precisely in order to decrypt messages. Counters may work in a perfect environment where all messages are delivered and retain the order. Otherwise, how can B figure out X?
Ah I see! When A sends the message to B, you also send nonce X with the message.
Therefore the "real" message you send to B is essentially toHex(encrypt(M)) + delimiter + toHex(nonce)
, where M
is a message and delimiter
is something like "$" to separate the message and the nonce. Note that I'm using toHex
to make the raw bytes into a human readable string, you could also use something like toBase64
to achieve the same thing.
Thus what you really send is something like 2DFE423ADFECCB$65ADBC21
which can be split and parsed easily by other participants in the conversation. You theoretically could store and send bytes, but transmitting bytes to other participants would require something like websockets and a different database; the whole thing would probably make your whole stack more complex than it has to be. So, just encode your bytes using toHex
or toBase64
and then send them just like you do any other regular string 🙂
I'm not saying that's the above is the only way to do it but it seems to be a reasonably good way 👍
The lazy version of the api does not provide an interface to encrypt a byte array (AsymmetricEncryptionActivity sample code). I want to convert a bitmap image to a byte array as below and encrypt it. How can I achieve this?
Also from my reading, I noticed that nonce should be generated by the messaging protocol so that it does not have to be transferred over the internet. Do you know a sample source code for a chat application which generates nonce so that chat users can encrypt and decrypt messages without tranfering nonce with the message?
Thank you.