Skip to content

Commit

Permalink
Fix ChaCha20 encryption for newer OpenSSL versions (#127)
Browse files Browse the repository at this point in the history
Co-authored-by: Kamil Wąż <[email protected]>
  • Loading branch information
Kamil Wąż and kamilwaz authored May 8, 2024
1 parent bcce42b commit 1b3ecdb
Showing 1 changed file with 15 additions and 4 deletions.
19 changes: 15 additions & 4 deletions lib/hap/crypto/cha_cha_20.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule HAP.Crypto.ChaCha20 do
@doc """
Takes a binary containing encrypted data followed by a 16 byte tag, verifies the tag
and decrypts the resultant data using the given key and nonce. Can take optional AAD
data which is authenticated under the auth_tag but not encrypted.
data which is authenticated under the auth_tag but not encrypted.
Returns `{:ok, plaintext}` or `{:error, message}`
"""
Expand All @@ -21,7 +21,7 @@ defmodule HAP.Crypto.ChaCha20 do
encrypted_data_length = byte_size(encrypted_data) - 16
<<encrypted_data::binary-size(encrypted_data_length), auth_tag::binary-16>> = encrypted_data

case :crypto.crypto_one_time_aead(:chacha20_poly1305, key, nonce, encrypted_data, aad, auth_tag, false) do
case :crypto.crypto_one_time_aead(:chacha20_poly1305, key, pad(nonce), encrypted_data, aad, auth_tag, false) do
:error -> {:error, "Message decryption error"}
result -> {:ok, result}
end
Expand All @@ -30,13 +30,24 @@ defmodule HAP.Crypto.ChaCha20 do
@doc """
Takes a plaintext binary and encrypts & tags it using the given key & nonce. Optionally takes
AAD data which is authenticated under the auth tag but not included in the returned binary (it is
up to the caller to convey the AAD to their counterparty).
up to the caller to convey the AAD to their counterparty).
Returns `{:ok, encrypted_data <> auth_tag}`
"""
@spec encrypt_and_tag(plaintext(), key(), nonce(), aad()) :: {:ok, ciphertext_with_authdata()}
def encrypt_and_tag(plaintext, key, nonce, aad \\ <<>>) do
{encrypted_data, auth_tag} = :crypto.crypto_one_time_aead(:chacha20_poly1305, key, nonce, plaintext, aad, true)
{encrypted_data, auth_tag} =
:crypto.crypto_one_time_aead(:chacha20_poly1305, key, pad(nonce), plaintext, aad, true)

{:ok, encrypted_data <> auth_tag}
end

@nonce_size 12

defp pad(nonce) when byte_size(nonce) >= @nonce_size, do: nonce

defp pad(nonce) do
bits = (@nonce_size - byte_size(nonce)) * 8
<<0::size(bits), nonce::binary>>
end
end

0 comments on commit 1b3ecdb

Please sign in to comment.