2019-07-01 15:24:26 +02:00
|
|
|
require "./lib_sodium"
|
|
|
|
require "./wipe"
|
|
|
|
require "./crypto_box/secret_key"
|
2019-07-01 19:37:45 +02:00
|
|
|
require "./nonce"
|
2019-06-28 13:32:16 +02:00
|
|
|
|
2019-07-01 15:24:26 +02:00
|
|
|
module Sodium
|
2019-08-06 23:27:19 +02:00
|
|
|
# Use Sodium::CryptoBox::SecretKey#box
|
2019-07-01 15:24:26 +02:00
|
|
|
class CryptoBox
|
2019-06-28 14:20:56 +02:00
|
|
|
include Wipe
|
|
|
|
|
2019-07-04 02:56:02 +02:00
|
|
|
MAC_SIZE = LibSodium.crypto_box_macbytes.to_i
|
2019-08-06 23:27:19 +02:00
|
|
|
# :nodoc:
|
|
|
|
NM_SIZE = LibSodium.crypto_box_beforenmbytes.to_i
|
|
|
|
raise "NM_SIZE=#{NM_SIZE}, assumed it was 32" if NM_SIZE != 32
|
2019-06-30 03:19:01 +02:00
|
|
|
|
2019-06-30 02:21:00 +02:00
|
|
|
@[Wipe::Var]
|
2019-08-06 23:27:19 +02:00
|
|
|
@key = StaticArray(UInt8, 32).new 0
|
2019-06-28 14:20:56 +02:00
|
|
|
|
2019-08-06 23:27:19 +02:00
|
|
|
# :nodoc:
|
|
|
|
# Used by SecretKey#box
|
2019-06-28 13:32:16 +02:00
|
|
|
def initialize(@secret_key : SecretKey, @public_key : PublicKey)
|
2019-08-06 23:27:19 +02:00
|
|
|
# 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
|
2019-06-28 13:32:16 +02:00
|
|
|
end
|
|
|
|
|
2019-08-06 13:09:08 +02:00
|
|
|
# Encrypts data and returns {ciphertext, nonce}
|
2019-08-06 12:30:16 +02:00
|
|
|
def encrypt(src)
|
|
|
|
encrypt src.to_slice
|
2019-06-28 13:32:16 +02:00
|
|
|
end
|
|
|
|
|
2019-08-06 13:09:08 +02:00
|
|
|
# Encrypts data and returns {ciphertext, nonce}
|
|
|
|
#
|
|
|
|
# Optionally supply a destination buffer.
|
|
|
|
def encrypt(src : Bytes, dst = Bytes.new(src.bytesize + MAC_SIZE), nonce = Nonce.new) : {Bytes, Nonce}
|
2019-08-06 23:27:19 +02:00
|
|
|
if LibSodium.crypto_box_easy_afternm(dst, src, src.bytesize, nonce.to_slice, @key.to_slice) != 0
|
2019-06-28 13:32:16 +02:00
|
|
|
raise Error.new("crypto_box_easy")
|
|
|
|
end
|
2019-07-01 19:37:45 +02:00
|
|
|
{dst, nonce}
|
2019-06-28 13:32:16 +02:00
|
|
|
end
|
|
|
|
|
2019-08-06 13:09:08 +02:00
|
|
|
# Returns decrypted message.
|
|
|
|
#
|
2019-08-06 12:30:16 +02:00
|
|
|
def decrypt(src)
|
|
|
|
decrypt src.to_slice
|
2019-07-01 15:24:26 +02:00
|
|
|
end
|
|
|
|
|
2019-08-06 13:09:08 +02:00
|
|
|
# Returns decrypted message.
|
|
|
|
#
|
|
|
|
# Optionally supply a destination buffer.
|
2019-08-06 23:27:19 +02:00
|
|
|
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
|
2019-06-28 13:32:16 +02:00
|
|
|
raise Error::DecryptionFailed.new("crypto_box_open_easy")
|
|
|
|
end
|
|
|
|
dst
|
|
|
|
end
|
|
|
|
|
|
|
|
# TODO detached
|
|
|
|
end
|
|
|
|
end
|