sodium.cr/src/sodium/crypto_box.cr

65 lines
1.9 KiB
Crystal

require "./lib_sodium"
require "./wipe"
require "./crypto_box/secret_key"
require "./nonce"
module Sodium
# Use Sodium::CryptoBox::SecretKey#box
class CryptoBox
include Wipe
MAC_SIZE = LibSodium.crypto_box_macbytes.to_i
# :nodoc:
NM_SIZE = LibSodium.crypto_box_beforenmbytes.to_i
raise "NM_SIZE=#{NM_SIZE}, assumed it was 32" if NM_SIZE != 32
@[Wipe::Var]
@key = StaticArray(UInt8, 32).new 0
# :nodoc:
# Used by SecretKey#box
def initialize(@secret_key : SecretKey, @public_key : PublicKey)
# Precalculate key for later use.
# Large speed gains with small data sizes and many messages.
# Small speed gains with large data sizes or few messages.
if LibSodium.crypto_box_beforenm(@key, @public_key.to_slice, @secret_key.to_slice) != 0
raise Error.new("crypto_box_beforenm")
end
end
# Encrypts data and returns {ciphertext, nonce}
def encrypt(src)
encrypt src.to_slice
end
# Encrypts data and returns {ciphertext, nonce}
#
# Optionally supply a destination buffer.
def encrypt(src : Bytes, dst = Bytes.new(src.bytesize + MAC_SIZE), nonce = Nonce.random) : {Bytes, Nonce}
nonce.used!
if LibSodium.crypto_box_easy_afternm(dst, src, src.bytesize, nonce.to_slice, @key.to_slice) != 0
raise Error.new("crypto_box_easy")
end
{dst, nonce}
end
# Returns decrypted message.
#
def decrypt(src)
decrypt src.to_slice
end
# Returns decrypted message.
#
# Optionally supply a destination buffer.
def decrypt(src : Bytes, dst = Bytes.new(src.bytesize - MAC_SIZE), nonce = Nonce.random) : Bytes
if LibSodium.crypto_box_open_easy_afternm(dst, src, src.bytesize, nonce.to_slice, @key) != 0
raise Error::DecryptionFailed.new("crypto_box_open_easy")
end
dst
end
# TODO detached
end
end