Sodium::Cipher::Aead::XChaCha20Poly1305Ietf Always use SecureBuffer. Rename.
parent
b212f6bacd
commit
d0f3100689
|
@ -26,7 +26,7 @@ private def box_from_test_vector(vec)
|
||||||
{box, nonce, plaintext, ciphertext}
|
{box, nonce, plaintext, ciphertext}
|
||||||
end
|
end
|
||||||
|
|
||||||
{% for name in %w(Xchacha20Poly1305Ietf) %}
|
{% for name in %w(XChaCha20Poly1305Ietf) %}
|
||||||
# TODO: verify against test vectors.
|
# TODO: verify against test vectors.
|
||||||
describe Sodium::Cipher::Aead::{{ name.id }} do
|
describe Sodium::Cipher::Aead::{{ name.id }} do
|
||||||
it "encrypts/decrypts in combined mode" do
|
it "encrypts/decrypts in combined mode" do
|
||||||
|
|
|
@ -4,17 +4,24 @@ require "../../nonce"
|
||||||
|
|
||||||
module Sodium::Cipher::Aead
|
module Sodium::Cipher::Aead
|
||||||
abstract class Chalsa
|
abstract class Chalsa
|
||||||
@key : Bytes | SecureBuffer
|
@key : SecureBuffer
|
||||||
|
|
||||||
|
# Initializes with a new random key.
|
||||||
def initialize
|
def initialize
|
||||||
@key = SecureBuffer.random key_size
|
@key = SecureBuffer.random key_size
|
||||||
end
|
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
|
raise ArgumentError.new("key size mismatch, got #{@key.bytesize}, wanted #{key_size}") if @key.bytesize != key_size
|
||||||
|
@key.readonly
|
||||||
end
|
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)
|
def encrypt(src, dst : Bytes? = nil, *, nonce = nil, additional = nil)
|
||||||
{Bytes, Nonce}
|
{Bytes, Nonce}
|
||||||
offset = src.bytesize
|
offset = src.bytesize
|
||||||
|
@ -24,7 +31,9 @@ module Sodium::Cipher::Aead
|
||||||
{dst, nonce}
|
{dst, nonce}
|
||||||
end
|
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
|
def decrypt(src, dst : Bytes? = nil, *, nonce : Nonce, additional = nil) : Bytes
|
||||||
src = src.to_slice
|
src = src.to_slice
|
||||||
offset = src.bytesize - mac_size
|
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
|
decrypt_detached src[0, offset], dst, nonce: nonce, mac: mac, additional: additional
|
||||||
end
|
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
|
def decrypt_string(src, dst : Bytes? = nil, *, nonce : Nonce, additional = nil) : String
|
||||||
buf = decrypt src, dst, nonce: nonce, additional: additional
|
buf = decrypt src, dst, nonce: nonce, additional: additional
|
||||||
# TODO: optimize
|
# TODO: optimize
|
||||||
|
@ -67,7 +78,7 @@ module Sodium::Cipher::Aead
|
||||||
protected abstract def mac_size : Int32
|
protected abstract def mac_size : Int32
|
||||||
end
|
end
|
||||||
|
|
||||||
{% for key, val in {"Xchacha20Poly1305Ietf" => "_xchacha20poly1305_ietf"} %}
|
{% for key, val in {"XChaCha20Poly1305Ietf" => "_xchacha20poly1305_ietf"} %}
|
||||||
# Use like `SecretBox` with optional additional authenticated data.
|
# 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)
|
# 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
|
ad_len = additional.try(&.bytesize) || 0
|
||||||
|
|
||||||
nonce.used!
|
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
|
@key.readonly do
|
||||||
raise Sodium::Error.new("crypto_aead_{{ val.id }}_encrypt_detached")
|
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)
|
||||||
end
|
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
|
raise Sodium::Error.new("crypto_aead_{{ val.id }}_encrypt_detached mac size mismatch") if mac_len != MAC_SIZE
|
||||||
|
end
|
||||||
|
|
||||||
{mac, dst, nonce}
|
{mac, dst, nonce}
|
||||||
end
|
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 `mac` and `nonce`
|
||||||
# Must supply `additional` if supplied to #encrypt_detached
|
# 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
|
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("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("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
|
raise ArgumentError.new("mac size mismatch, got #{mac.bytesize}, wanted #{MAC_SIZE}") unless mac.bytesize == MAC_SIZE
|
||||||
|
|
||||||
ad_len = additional.try(&.bytesize) || 0
|
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
|
r = @key.readonly do
|
||||||
raise Sodium::Error::DecryptionFailed.new("crypto_aead_{{ val.id }}_decrypt_detached")
|
LibSodium.crypto_aead{{ val.id }}_decrypt_detached(dst, nil, src, src.bytesize, mac, additional, ad_len, nonce.to_slice, @key.to_slice)
|
||||||
end
|
end
|
||||||
|
raise Sodium::Error::DecryptionFailed.new("crypto_aead_{{ val.id }}_decrypt_detached") if r != 0
|
||||||
dst
|
dst
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue