Sodium::Cipher::Aead::XChaCha20Poly1305Ietf Always use SecureBuffer. Rename.

master
Didactic Drunk 2019-09-13 22:39:29 -07:00
parent b212f6bacd
commit d0f3100689
2 changed files with 27 additions and 14 deletions

View File

@ -26,7 +26,7 @@ private def box_from_test_vector(vec)
{box, nonce, plaintext, ciphertext}
end
{% for name in %w(Xchacha20Poly1305Ietf) %}
{% for name in %w(XChaCha20Poly1305Ietf) %}
# TODO: verify against test vectors.
describe Sodium::Cipher::Aead::{{ name.id }} do
it "encrypts/decrypts in combined mode" do

View File

@ -4,17 +4,24 @@ require "../../nonce"
module Sodium::Cipher::Aead
abstract class Chalsa
@key : Bytes | SecureBuffer
@key : SecureBuffer
# Initializes with a new random key.
def initialize
@key = SecureBuffer.random key_size
end
def initialize(@key)
def initialize(@key : Securebuffer)
raise ArgumentError.new("key size mismatch, got #{@key.bytesize}, wanted #{key_size}") if @key.bytesize != key_size
@key.readonly
end
# Encrypts data and returns {ciphertext, nonce}
def initialize(bytes : Bytes, erase = false)
raise ArgumentError.new("key size mismatch, got #{bytes.bytesize}, wanted #{key_size}") if bytes.bytesize != key_size
@key = SecureBuffer.new bytes, erase: erase
end
# Encrypts `src` and returns {ciphertext, nonce}
def encrypt(src, dst : Bytes? = nil, *, nonce = nil, additional = nil)
{Bytes, Nonce}
offset = src.bytesize
@ -24,7 +31,9 @@ module Sodium::Cipher::Aead
{dst, nonce}
end
# Decrypts data and returns plaintext
# Decrypts `src` and returns plaintext
# Must supply `nonce`
# Must supply `additional` if supplied to #encrypt
def decrypt(src, dst : Bytes? = nil, *, nonce : Nonce, additional = nil) : Bytes
src = src.to_slice
offset = src.bytesize - mac_size
@ -33,7 +42,9 @@ module Sodium::Cipher::Aead
decrypt_detached src[0, offset], dst, nonce: nonce, mac: mac, additional: additional
end
# Decrypts data and returns plaintext
# Decrypts `src` and returns plaintext
# Must supply `nonce`
# Must supply `additional` if supplied to #encrypt
def decrypt_string(src, dst : Bytes? = nil, *, nonce : Nonce, additional = nil) : String
buf = decrypt src, dst, nonce: nonce, additional: additional
# TODO: optimize
@ -67,7 +78,7 @@ module Sodium::Cipher::Aead
protected abstract def mac_size : Int32
end
{% for key, val in {"Xchacha20Poly1305Ietf" => "_xchacha20poly1305_ietf"} %}
{% for key, val in {"XChaCha20Poly1305Ietf" => "_xchacha20poly1305_ietf"} %}
# Use like `SecretBox` with optional additional authenticated data.
#
# See [https://libsodium.gitbook.io/doc/secret-key_cryptography/aead](https://libsodium.gitbook.io/doc/secret-key_cryptography/aead)
@ -96,28 +107,30 @@ module Sodium::Cipher::Aead
ad_len = additional.try(&.bytesize) || 0
nonce.used!
if LibSodium.crypto_aead{{ val.id }}_encrypt_detached(dst, mac, out mac_len, src, src.bytesize, additional, ad_len, nil, nonce.to_slice, @key.to_slice) != 0
raise Sodium::Error.new("crypto_aead_{{ val.id }}_encrypt_detached")
end
@key.readonly do
r = LibSodium.crypto_aead{{ val.id }}_encrypt_detached(dst, mac, out mac_len, src, src.bytesize, additional, ad_len, nil, nonce.to_slice, @key.to_slice)
raise Sodium::Error.new("crypto_aead_{{ val.id }}_encrypt_detached") if r != 0
raise Sodium::Error.new("crypto_aead_{{ val.id }}_encrypt_detached mac size mismatch") if mac_len != MAC_SIZE
end
{mac, dst, nonce}
end
# src and dst may be the same object but should not overlap.
# `src` and `dst` may be the same object but should not overlap.
# Must supply `mac` and `nonce`
# Must supply `additional` if supplied to #encrypt_detached
def decrypt_detached(src : Bytes, dst : Bytes? = nil, *, nonce : Sodium::Nonce, mac : Bytes, additional : String | Bytes | Nil = nil) : Bytes
dst ||= Bytes.new(src.bytesize)
dst ||= Bytes.new src.bytesize
raise ArgumentError.new("src and dst bytesize must be identical") if src.bytesize != dst.bytesize
raise ArgumentError.new("nonce size mismatch, got #{nonce.bytesize}, wanted #{NONCE_SIZE}") unless nonce.bytesize == NONCE_SIZE
raise ArgumentError.new("mac size mismatch, got #{mac.bytesize}, wanted #{MAC_SIZE}") unless mac.bytesize == MAC_SIZE
ad_len = additional.try(&.bytesize) || 0
if LibSodium.crypto_aead{{ val.id }}_decrypt_detached(dst, nil, src, src.bytesize, mac, additional, ad_len, nonce.to_slice, @key.to_slice) != 0
raise Sodium::Error::DecryptionFailed.new("crypto_aead_{{ val.id }}_decrypt_detached")
r = @key.readonly do
LibSodium.crypto_aead{{ val.id }}_decrypt_detached(dst, nil, src, src.bytesize, mac, additional, ad_len, nonce.to_slice, @key.to_slice)
end
raise Sodium::Error::DecryptionFailed.new("crypto_aead_{{ val.id }}_decrypt_detached") if r != 0
dst
end