Dear crystal community,
I was having a lot of fun implementing RFC 8439 in Crystal. This might not be a very well known RFC. It mainly talkes about the Cipher ChaCha20 the Authenticator Poly1305 and an application in the AEAD mode which allows to create authenticated cipher text with additional data.
Here is the repo link: GitHub - threez/rfc8439.cr: Crystal implementation ChaCha20 stream cipher as well as the Poly1305 authenticator and the AEAD mode defined in rfc8439.
Here a preview of how it is to use it:
require "rfc8439"
# key and nonce are usually given using Bytes,
# but for convinience can be done as a hex string
key = "00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f"
nonce = "00:00:00:09:00:00:00:4a:00:00:00:00"
msg = "Hello World".to_slice
cipher = Crypto::ChaCha20.new(key, nonce)
encrypted = cipher.encrypt(msg)
# encryption is done using XOR so decryption is done
# by encrypting the cypher text
cipher = Crypto::ChaCha20.new(key, nonce)
plaintext = cipher.encrypt(encrypted)
puts plaintext
The reason that I’m writing, besides sharing my fun project is, that I wanted to raise a few questions:
- How do you feel about implementing crypto in Crystal in general. Currently we have a heavy depenency on OpenSSL which has its pros and cons, and languages like Go and Java went to implement them natively in the language.
- What do you think about my implementation? Is it readable, is it idiomatic?
- I was trying to optimize the perfromance of the implmentation and got to encrypt 1 GB in 3 sec on my machine (emulated linux). I have a good intuition on how to optimize code in C/C++ and Go but must admit, that I find it rather difficult to do the same in Crystal. Performance - Crystal doesn’t contain all to many infos that helped my, and I would like to make it a little faster without hurting readability of the code much. I lack the tooling that helps me to identitfy the next steps and maybe didn’t find the right material.
Thanks