Merge pull request #2 from dorkrawk/master

Add libsodium Public-key Signature Functionality
master
Andrew Hamon 2018-02-16 16:14:43 -05:00 committed by GitHub
commit 2d0f329774
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 135 additions and 9 deletions

View File

@ -40,6 +40,19 @@ nonce, encrypted = Cox.encrypt(data, bob.public, alice.secret)
decrypted = Cox.decrypt(encrypted, nonce, alice.public, bob.secret) decrypted = Cox.decrypt(encrypted, nonce, alice.public, bob.secret)
String.new(decrypted) # => "Hello World!" String.new(decrypted) # => "Hello World!"
# Public key signing
message = "Hello World!"
signing_pair = Cox::SignKeyPair.new
# Sign the message
signature = Cox.sign_detached(message, signing_pair.secret)
# And verify
Cox.verify_detached(signature, message, signing_pair.public) # => true
``` ```
## Contributing ## Contributing
@ -53,3 +66,4 @@ String.new(decrypted) # => "Hello World!"
## Contributors ## Contributors
- [andrewhamon](https://github.com/andrewhamon) Andrew Hamon - creator, maintainer - [andrewhamon](https://github.com/andrewhamon) Andrew Hamon - creator, maintainer
- [dorkrawk](https://github.com/dorkrawk) Dave Schwantes - contributor

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_detached(message, signing_pair.secret)
# Verify the signature on the message
verified = Cox.verify_detached(signature, message, signing_pair.public)
verified.should eq(true)
end
end end

View File

@ -21,6 +21,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_detached(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_detached(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