added basic libsodium public key signature sign/verify functionality

master
Dave 2018-02-11 23:06:34 -08:00
parent 057f093a32
commit 3fa19b57e3
7 changed files with 128 additions and 1 deletions

View File

@ -3,7 +3,7 @@ require "./spec_helper"
describe Cox do describe Cox do
# TODO: Write tests # TODO: Write tests
it "works" do it "works for encrypting" do
data = "Hello World!" data = "Hello World!"
# Alice is the sender # Alice is the sender
@ -22,4 +22,18 @@ describe Cox do
String.new(decrypted).should eq(data) String.new(decrypted).should eq(data)
end end
it "works for signing" do
message = "test"
signing_pair = Cox::SignKeyPair.new
# Create signature using the secret key
signature = Cox.sign(message, signing_pair.secret)
# Verify the signature on the message
verified = Cox.verify(signature, message, signing_pair.public)
verified.should eq(true)
end
end end

View File

@ -22,6 +22,24 @@ module Cox
LibSodium.crypto_box_open_easy(output_buffer.to_unsafe, data_buffer.to_unsafe, data_size, nonce.pointer, sender_public_key.pointer, recipient_secret_key.pointer) LibSodium.crypto_box_open_easy(output_buffer.to_unsafe, data_buffer.to_unsafe, data_size, nonce.pointer, sender_public_key.pointer, recipient_secret_key.pointer)
output_buffer output_buffer
end end
def self.sign(message, secret_key : SignSecretKey)
message_buffer = message.to_slice
message_buffer_size = message_buffer.bytesize
signature_output_buffer = Bytes.new(LibSodium::SIGNATURE_BYTES)
LibSodium.crypto_sign_detached(signature_output_buffer.to_unsafe, 0, message_buffer.to_unsafe, message_buffer_size, secret_key.pointer)
signature_output_buffer
end
def self.verify(signature, message, public_key : SignPublicKey)
signature_buffer = signature.to_slice
message_buffer = message.to_slice
message_buffer_size = message_buffer.bytesize
verified = LibSodium.crypto_sign_verify_detached(signature_buffer.to_unsafe, message_buffer.to_unsafe, message_buffer_size, public_key.pointer)
verified.zero?
end
end end
if Cox::LibSodium.sodium_init() == -1 if Cox::LibSodium.sodium_init() == -1

View File

@ -7,11 +7,17 @@ module Cox
fun crypto_box_secretkeybytes() : LibC::SizeT fun crypto_box_secretkeybytes() : LibC::SizeT
fun crypto_box_noncebytes() : LibC::SizeT fun crypto_box_noncebytes() : LibC::SizeT
fun crypto_box_macbytes() : LibC::SizeT fun crypto_box_macbytes() : LibC::SizeT
fun crypto_sign_publickeybytes() : LibC::SizeT
fun crypto_sign_secretkeybytes() : LibC::SizeT
fun crypto_sign_bytes() : LibC::SizeT
PUBLIC_KEY_BYTES = crypto_box_publickeybytes() PUBLIC_KEY_BYTES = crypto_box_publickeybytes()
SECRET_KEY_BYTES = crypto_box_secretkeybytes() SECRET_KEY_BYTES = crypto_box_secretkeybytes()
NONCE_BYTES = crypto_box_macbytes() NONCE_BYTES = crypto_box_macbytes()
MAC_BYTES = crypto_box_macbytes() MAC_BYTES = crypto_box_macbytes()
PUBLIC_SIGN_BYTES = crypto_sign_publickeybytes()
SECRET_SIGN_BYTES = crypto_sign_secretkeybytes()
SIGNATURE_BYTES = crypto_sign_bytes()
fun crypto_box_keypair( fun crypto_box_keypair(
public_key_output : Pointer(LibC::UChar), public_key_output : Pointer(LibC::UChar),
@ -35,5 +41,25 @@ module Cox
sender_public_key : Pointer(LibC::UChar), sender_public_key : Pointer(LibC::UChar),
recipient_secret_key : Pointer(LibC::UChar) recipient_secret_key : Pointer(LibC::UChar)
) : LibC::Int ) : LibC::Int
fun crypto_sign_keypair(
public_key_output : Pointer(LibC::UChar),
secret_key_output : Pointer(LibC::UChar)
) : LibC::Int
fun crypto_sign_detached(
signature_output : Pointer(LibC::UChar),
signature_output_size : LibC::ULongLong,
message : Pointer(LibC::UChar),
message_size : LibC::ULongLong,
secret_key : Pointer(LibC::UChar)
) : LibC::Int
fun crypto_sign_verify_detached(
signature : Pointer(LibC::UChar),
message : Pointer(LibC::UChar),
message_size : LibC::ULongLong,
public_key : Pointer(LibC::UChar)
) : LibC::Int
end end
end end

24
src/cox/sign_key_pair.cr Normal file
View File

@ -0,0 +1,24 @@
require "./lib_sodium"
module Cox
class SignKeyPair
property public : SignPublicKey
property secret : SignSecretKey
def initialize(@public, @secret)
end
def self.new(pub : Bytes, sec : Bytes)
new(SignPublicKey.new(pub), SignSecretKey.new(sec))
end
def self.new
public_key = Bytes.new(SignPublicKey::KEY_LENGTH)
secret_key = Bytes.new(SignSecretKey::KEY_LENGTH)
LibSodium.crypto_sign_keypair(public_key.to_unsafe, secret_key.to_unsafe)
new(public_key, secret_key)
end
end
end

View File

@ -0,0 +1,15 @@
require "./lib_sodium"
module Cox
class SignPublicKey < Key
property bytes : Bytes
KEY_LENGTH = LibSodium::PUBLIC_SIGN_BYTES
def initialize(@bytes : Bytes)
if bytes.bytesize != KEY_LENGTH
raise ArgumentError.new("Public key must be #{KEY_LENGTH} bytes, got #{bytes.bytesize}")
end
end
end
end

View File

@ -0,0 +1,15 @@
require "./lib_sodium"
module Cox
class SignSecretKey < Key
property bytes : Bytes
KEY_LENGTH = LibSodium::SECRET_SIGN_BYTES
def initialize(@bytes : Bytes)
if bytes.bytesize != KEY_LENGTH
raise ArgumentError.new("Secret key must be #{KEY_LENGTH} bytes, got #{bytes.bytesize}")
end
end
end
end

15
src/cox/signature.cr Normal file
View File

@ -0,0 +1,15 @@
require "./lib_sodium"
module Cox
class Signature
property bytes : Bytes
KEY_LENGTH = LibSodium::SIGNATURE_BYTES
def initialize(@bytes : Bytes)
if bytes.bytesize != KEY_LENGTH
raise ArgumentError.new("Signature must be #{KEY_LENGTH} bytes, got #{bytes.bytesize}")
end
end
end
end