Use crypto_box_beforenmbytes to precompute CryptoBox shared key.

master
Didactic Drunk 2019-08-06 14:27:19 -07:00
parent 31c3ead851
commit d556e1c909
6 changed files with 61 additions and 25 deletions

View File

@ -7,6 +7,11 @@ require "../src/sodium"
{% end %} {% end %}
puts "" puts ""
{% for name in %w(MAC_SIZE NM_SIZE) %}
puts "Sodium::CryptoBox::{{ name.id }} #{Sodium::CryptoBox::{{ name.id }}}"
{% end %}
puts ""
{% for name in %w(KEY_SIZE SEED_SIZE SIG_SIZE) %} {% for name in %w(KEY_SIZE SEED_SIZE SIG_SIZE) %}
puts "Sodium::Sign::SecretKey::{{ name.id }} #{Sodium::Sign::SecretKey::{{ name.id }}}" puts "Sodium::Sign::SecretKey::{{ name.id }} #{Sodium::Sign::SecretKey::{{ name.id }}}"
{% end %} {% end %}

View File

@ -4,17 +4,27 @@ require "./crypto_box/secret_key"
require "./nonce" require "./nonce"
module Sodium module Sodium
# Use Sodium::CryptoBox::SecretKey#box
class CryptoBox class CryptoBox
include Wipe include Wipe
MAC_SIZE = LibSodium.crypto_box_macbytes.to_i 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
# BUG: precompute size
@[Wipe::Var] @[Wipe::Var]
@bytes = Bytes.new(1) @key = StaticArray(UInt8, 32).new 0
# :nodoc:
# Used by SecretKey#box
def initialize(@secret_key : SecretKey, @public_key : PublicKey) def initialize(@secret_key : SecretKey, @public_key : PublicKey)
# TODO: precompute using crypto_box_beforenm # 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 end
# Encrypts data and returns {ciphertext, nonce} # Encrypts data and returns {ciphertext, nonce}
@ -26,7 +36,7 @@ module Sodium
# #
# Optionally supply a destination buffer. # Optionally supply a destination buffer.
def encrypt(src : Bytes, dst = Bytes.new(src.bytesize + MAC_SIZE), nonce = Nonce.new) : {Bytes, Nonce} def encrypt(src : Bytes, dst = Bytes.new(src.bytesize + MAC_SIZE), nonce = Nonce.new) : {Bytes, Nonce}
if LibSodium.crypto_box_easy(dst, src, src.bytesize, nonce.to_slice, @public_key.to_slice, @secret_key.to_slice) != 0 if LibSodium.crypto_box_easy_afternm(dst, src, src.bytesize, nonce.to_slice, @key.to_slice) != 0
raise Error.new("crypto_box_easy") raise Error.new("crypto_box_easy")
end end
{dst, nonce} {dst, nonce}
@ -41,8 +51,8 @@ module Sodium
# Returns decrypted message. # Returns decrypted message.
# #
# Optionally supply a destination buffer. # Optionally supply a destination buffer.
def decrypt(src : Bytes, dst = Bytes.new(src.bytesize - MAC_SIZE), nonce = Nonce.new) : Bytes def decrypt(src : Bytes, dst = Bytes.new(src.bytesize - MAC_SIZE), nonce = Nonce.random) : Bytes
if LibSodium.crypto_box_open_easy(dst, src, src.bytesize, nonce.to_slice, @public_key.to_slice, @secret_key.to_slice) != 0 if LibSodium.crypto_box_open_easy_afternm(dst, src, src.bytesize, nonce.to_slice, @key) != 0
raise Error::DecryptionFailed.new("crypto_box_open_easy") raise Error::DecryptionFailed.new("crypto_box_open_easy")
end end
dst dst

View File

@ -5,8 +5,6 @@ require "../crypto_box"
class Sodium::CryptoBox class Sodium::CryptoBox
# Key used for encryption + authentication or encryption without authentication, not for unencrypted signing. # Key used for encryption + authentication or encryption without authentication, not for unencrypted signing.
#
# If you don't want this behavior pass a duplicate of the key/seed to initialize().
class SecretKey < Key class SecretKey < Key
KEY_SIZE = LibSodium.crypto_box_secretkeybytes.to_i KEY_SIZE = LibSodium.crypto_box_secretkeybytes.to_i
SEED_SIZE = LibSodium.crypto_box_seedbytes.to_i SEED_SIZE = LibSodium.crypto_box_seedbytes.to_i

View File

@ -12,6 +12,7 @@ module Sodium
fun crypto_box_noncebytes : LibC::SizeT fun crypto_box_noncebytes : LibC::SizeT
fun crypto_box_sealbytes : LibC::SizeT fun crypto_box_sealbytes : LibC::SizeT
fun crypto_box_macbytes : LibC::SizeT fun crypto_box_macbytes : LibC::SizeT
fun crypto_box_beforenmbytes : LibC::SizeT
fun crypto_sign_publickeybytes : LibC::SizeT fun crypto_sign_publickeybytes : LibC::SizeT
fun crypto_sign_secretkeybytes : LibC::SizeT fun crypto_sign_secretkeybytes : LibC::SizeT
fun crypto_sign_bytes : LibC::SizeT fun crypto_sign_bytes : LibC::SizeT
@ -148,22 +149,45 @@ module Sodium
secret_key_output : Pointer(LibC::UChar) secret_key_output : Pointer(LibC::UChar)
) : LibC::Int ) : LibC::Int
fun crypto_box_easy( fun crypto_box_beforenm(
output : Pointer(LibC::UChar), k : Pointer(LibC::UChar),
data : Pointer(LibC::UChar), pk : Pointer(LibC::UChar),
data_size : LibC::ULongLong, sk : Pointer(LibC::UChar)
nonce : Pointer(LibC::UChar),
recipient_public_key : Pointer(LibC::UChar),
sender_secret_key : Pointer(LibC::UChar)
) : LibC::Int ) : LibC::Int
fun crypto_box_open_easy( fun crypto_box_easy_afternm(
output : Pointer(LibC::UChar), output : Pointer(LibC::UChar),
data : Pointer(LibC::UChar), data : Pointer(LibC::UChar),
data_size : LibC::ULongLong, data_size : LibC::ULongLong,
nonce : Pointer(LibC::UChar), nonce : Pointer(LibC::UChar),
sender_public_key : Pointer(LibC::UChar), key : Pointer(LibC::UChar)
recipient_secret_key : Pointer(LibC::UChar) ) : LibC::Int
# TODO: possibly remove after switching to detached
fun crypto_box_open_easy_afternm(
output : Pointer(LibC::UChar),
data : Pointer(LibC::UChar),
data_size : LibC::ULongLong,
nonce : Pointer(LibC::UChar),
key : Pointer(LibC::UChar)
) : LibC::Int
fun crypto_box_detached_afternm(
output : Pointer(LibC::UChar),
mac : Pointer(LibC::UChar),
data : Pointer(LibC::UChar),
data_size : LibC::ULongLong,
nonce : Pointer(LibC::UChar),
key : Pointer(LibC::UChar)
) : LibC::Int
fun crypto_box_open_detached_afternm(
output : Pointer(LibC::UChar),
data : Pointer(LibC::UChar),
mac : Pointer(LibC::UChar),
data_size : LibC::ULongLong,
nonce : Pointer(LibC::UChar),
key : Pointer(LibC::UChar)
) : LibC::Int ) : LibC::Int
fun crypto_box_seal( fun crypto_box_seal(
@ -294,8 +318,7 @@ module Sodium
end end
end end
# Constant time memory compare. # Constant time memory compare. Raises unless comparison succeeds.
# Raises unless comparison succeeds.
def self.memcmp!(a, b) def self.memcmp!(a, b)
raise Error::MemcmpFailed.new unless memcmp(a, b) raise Error::MemcmpFailed.new unless memcmp(a, b)
true true

View File

@ -2,12 +2,12 @@ require "./lib_sodium"
require "./wipe" require "./wipe"
module Sodium module Sodium
# Allocate guarded memory using [sodium_malloc](https://libsodium.gitbook.io/doc/memory_management)
class SecureBuffer class SecureBuffer
getter bytesize getter bytesize
delegate :+, :[], :[]=, to: to_slice delegate :+, :[], :[]=, to: to_slice
# Allocate guarded memory using [sodium_malloc](https://libsodium.gitbook.io/doc/memory_management)
def initialize(@bytesize : Int32) def initialize(@bytesize : Int32)
@ptr = LibSodium.sodium_malloc @bytesize @ptr = LibSodium.sodium_malloc @bytesize
end end

View File

@ -3,15 +3,15 @@ require "../key"
require "./public_key" require "./public_key"
module Sodium module Sodium
# Key used for signing/verification only. # Ed25519 secret key used for signing.
# #
# If you don't want this behavior pass a duplicate of the key/seed to initialize(). # [https://libsodium.gitbook.io/doc/public-key_cryptography/public-key_signatures](https://libsodium.gitbook.io/doc/public-key_cryptography/public-key_signatures)
# #
# Usage: # Usage:
# ``` # ```
# key = SecretKey.new # key = Sodium::Sign::SecretKey.new
# sig = key.sign_detached data # sig = key.sign_detached data
# key.public_key.verify_detached data # key.public_key.verify_detached data, sig
# ``` # ```
class Sign::SecretKey < Sodium::Key class Sign::SecretKey < Sodium::Key
KEY_SIZE = LibSodium.crypto_sign_secretkeybytes.to_i KEY_SIZE = LibSodium.crypto_sign_secretkeybytes.to_i