ffi-libsodium 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,41 @@
1
+ require_relative '../sodium'
2
+ require_relative '../sodium/utils'
3
+ require_relative '../sodium/buffer'
4
+ require_relative '../sodium/secret_buffer'
5
+
6
+ module Crypto
7
+ module ShortHash
8
+ extend FFI::Library
9
+ extend Sodium::Utils
10
+
11
+ ffi_lib :libsodium
12
+
13
+ attach_function :primitive, :crypto_shorthash_primitive, [], :string
14
+ attach_function :bytes, :crypto_shorthash_bytes, [], :size_t
15
+ attach_function :keybytes, :crypto_shorthash_keybytes, [], :size_t
16
+
17
+ PRIMITIVE = primitive.freeze
18
+ BYTES = bytes.freeze
19
+ KEYBYTES = keybytes.freeze
20
+
21
+ attach_function :crypto_shorthash, [:buffer_out, :buffer_in, :ulong_long, :buffer_in], :int
22
+
23
+ module_function
24
+
25
+ def shorthash(short_data, key)
26
+ short_data_len = get_size(short_data)
27
+ check_length(key, KEYBYTES, :SecretKey)
28
+
29
+ siphash = Sodium::Buffer.new(:uchar, BYTES)
30
+ key.readonly if key.is_a?(Sodium::SecretBuffer)
31
+ crypto_shorthash(siphash, short_data, short_data_len, key)
32
+ key.noaccess if key.is_a?(Sodium::SecretBuffer)
33
+
34
+ siphash
35
+ end
36
+ end
37
+
38
+ def self.shorthash(*args)
39
+ ShortHash.shorthash(*args)
40
+ end
41
+ end
@@ -0,0 +1,102 @@
1
+ require_relative '../sodium'
2
+ require_relative '../sodium/utils'
3
+ require_relative '../sodium/buffer'
4
+ require_relative '../sodium/secret_buffer'
5
+ require_relative '../random_bytes'
6
+
7
+ module Crypto
8
+ module Sign
9
+ extend FFI::Library
10
+ extend Sodium::Utils
11
+
12
+ ffi_lib :libsodium
13
+
14
+ attach_function :primitive, :crypto_sign_primitive, [], :string
15
+ attach_function :bytes, :crypto_sign_bytes, [], :size_t
16
+ attach_function :seedbytes, :crypto_sign_seedbytes, [], :size_t
17
+ attach_function :publickeybytes, :crypto_sign_publickeybytes, [], :size_t
18
+ attach_function :secretkeybytes, :crypto_sign_secretkeybytes, [], :size_t
19
+
20
+ PRIMITIVE = primitive.freeze
21
+ BYTES = bytes.freeze
22
+ SEEDBYTES = seedbytes.freeze
23
+ PUBLICKEYBYTES = publickeybytes.freeze
24
+ SECRETKEYBYTES = secretkeybytes.freeze
25
+
26
+ attach_function :crypto_sign_keypair, [:buffer_out, :buffer_out], :int
27
+ attach_function :crypto_sign_seed_keypair, [:buffer_out, :buffer_out, :buffer_in], :int
28
+
29
+ attach_function :crypto_sign, [:buffer_out, :buffer_out, :buffer_in, :ulong_long, :buffer_in], :int
30
+ attach_function :crypto_sign_open, [:buffer_out, :buffer_out, :buffer_in, :ulong_long, :buffer_in], :int
31
+
32
+ module_function
33
+
34
+ def keypair
35
+ public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
36
+ secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
37
+
38
+ crypto_sign_keypair(public_key, secret_key)
39
+
40
+ [public_key, secret_key]
41
+ end
42
+
43
+ def seed_keypair(seed)
44
+ check_length(seed, SEEDBYTES, :Seed)
45
+
46
+ public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
47
+ secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
48
+
49
+ crypto_sign_seed_keypair(public_key, secret_key, seed)
50
+
51
+ [public_key, secret_key]
52
+ end
53
+
54
+ def memory_locked_keypair
55
+ public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
56
+ secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES)
57
+ crypto_sign_keypair(public_key, secret_key)
58
+ secret_key.noaccess
59
+
60
+ [public_key, secret_key]
61
+ end
62
+
63
+ def memory_locked_seed_keypair(seed)
64
+ check_length(seed, SEEDBYTES, :Seed)
65
+
66
+ public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
67
+ secret_key = Sodium::SecretBuffer.new(:uchar, SECRETKEYBYTES)
68
+ crypto_sign_seed_keypair(public_key, secret_key, seed)
69
+ secret_key.noaccess
70
+
71
+ [public_key, secret_key]
72
+ end
73
+
74
+ def sign(message, secret_key)
75
+ message_len = get_size(message)
76
+ check_length(secret_key, SECRETKEYBYTES, :SecretKey)
77
+
78
+ sealed_message = FFI::MemoryPointer.new(:uchar, BYTES + message_len)
79
+ sealed_message_len = FFI::MemoryPointer.new(:ulong_long)
80
+ secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
81
+ crypto_sign(sealed_message, sealed_message_len, message, message_len, secret_key)
82
+ secret_key.noaccess if secret_key.is_a?(Sodium::SecretBuffer)
83
+
84
+ [sealed_message, sealed_message_len.read_ulong_long]
85
+ end
86
+
87
+ def open(sealed_message, smlen, public_key)
88
+ sealed_message_len = get_int(smlen)
89
+ check_length(public_key, PUBLICKEYBYTES, :PublicKey)
90
+
91
+ unsealed_message = FFI::MemoryPointer.new(:uchar, sealed_message_len)
92
+ unsealed_message_len = FFI::MemoryPointer.new(:ulong_long)
93
+ crypto_sign_open(unsealed_message, unsealed_message_len, sealed_message, sealed_message_len, public_key)
94
+
95
+ [unsealed_message, unsealed_message_len.read_ulong_long]
96
+ end
97
+ end
98
+
99
+ def self.sign(*args)
100
+ Sign.sign(*args)
101
+ end
102
+ end
data/lib/libsodium.rb ADDED
@@ -0,0 +1,21 @@
1
+ require_relative 'sodium'
2
+ require_relative 'sodium/utils'
3
+ require_relative 'sodium/buffer'
4
+ require_relative 'sodium/secret_buffer'
5
+ require_relative 'random_bytes'
6
+ require_relative 'crypto/secret_box'
7
+ require_relative 'crypto/auth'
8
+ require_relative 'crypto/aead/chacha20_poly1305'
9
+ require_relative 'crypto/box'
10
+ require_relative 'crypto/sign'
11
+ require_relative 'crypto/generic_hash'
12
+ require_relative 'crypto/short_hash'
13
+ require_relative 'crypto/pw_hash/scrypt_salsa208_sha256'
14
+ require_relative 'crypto/one_time_auth'
15
+ require_relative 'crypto/scalar_mult'
16
+
17
+ Thread.exclusive do
18
+ if Sodium.init == -1
19
+ fail LoadError, 'Could not initialize sodium'
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'sodium/buffer'
2
+
3
+ module RandomBytes
4
+ extend FFI::Library
5
+ ffi_lib :libsodium
6
+
7
+ attach_function :randombytes_buf, [:buffer_out, :size_t], :void, blocking: true
8
+
9
+ attach_function :random, :randombytes_random, [], :uint32, blocking: true
10
+ attach_function :uniform, :randombytes_uniform, [:uint32], :uint32, blocking: true
11
+ attach_function :close, :randombytes_close, [], :int, blocking: true
12
+ attach_function :stir, :randombytes_stir, [], :void, blocking: true
13
+
14
+ module_function
15
+
16
+ def buf(size)
17
+ buf = Sodium::Buffer.new(:uchar, size)
18
+ randombytes_buf(buf, size)
19
+ buf
20
+ end
21
+ end
data/lib/sodium.rb ADDED
@@ -0,0 +1,69 @@
1
+ require 'ffi'
2
+
3
+ module Sodium
4
+ class CryptoError < StandardError; end
5
+ class LengthError < ArgumentError; end
6
+ class MemoryError < StandardError; end
7
+
8
+ extend FFI::Library
9
+ ffi_lib :libsodium
10
+
11
+ attach_function :init, :sodium_init, [], :int, blocking: true
12
+
13
+ attach_function :memcmp, :sodium_memcmp, [:buffer_in, :buffer_in, :size_t], :int
14
+ attach_function :memzero, :sodium_memzero, [:pointer, :size_t], :void, blocking: true
15
+ attach_function :free, :sodium_free, [:pointer], :void, blocking: true
16
+ attach_function :sodium_mlock, [:pointer, :size_t], :int, blocking: true
17
+ attach_function :sodium_munlock, [:pointer, :size_t], :int, blocking: true
18
+ attach_function :sodium_malloc, [:size_t], :pointer, blocking: true
19
+ attach_function :sodium_allocarray, [:size_t, :size_t], :pointer, blocking: true
20
+ attach_function :sodium_mprotect_noaccess, [:pointer], :int, blocking: true
21
+ attach_function :sodium_mprotect_readonly, [:pointer], :int, blocking: true
22
+ attach_function :sodium_mprotect_readwrite, [:pointer], :int, blocking: true
23
+
24
+ module_function
25
+
26
+ def mlock(addr, len)
27
+ if sodium_mlock(addr, len) == -1
28
+ raise MemoryError, "Could not lock length=#{len.to_int} bytes memory at address=#{addr.address}", caller
29
+ end
30
+ end
31
+
32
+ def munlock(addr, len)
33
+ if sodium_munlock(addr, len) == -1
34
+ raise MemoryError, "Could not unlock length=#{len.to_int} bytes memory at address=#{addr.address}", caller
35
+ end
36
+ end
37
+
38
+ def malloc(size)
39
+ unless (mem = sodium_malloc(size))
40
+ raise NoMemoryError, "Failed to allocate memory size=#{size.to_int} bytes", caller
41
+ end
42
+ mem
43
+ end
44
+
45
+ def allocarray(count, size)
46
+ unless (mem = sodium_allocarray(count, size))
47
+ raise NoMemoryError, "Failed to allocate memory size=#{count.to_int * size.to_int} bytes", caller
48
+ end
49
+ mem
50
+ end
51
+
52
+ def noaccess(ptr)
53
+ if sodium_mprotect_noaccess(ptr) == -1
54
+ raise MemoryError, "Memory at address=#{ptr.address} is not secured with #{self}.malloc", caller
55
+ end
56
+ end
57
+
58
+ def readonly(ptr)
59
+ if sodium_mprotect_readonly(ptr) == -1
60
+ raise MemoryError, "Memory at address=#{ptr.address} is not secured with #{self}.malloc", caller
61
+ end
62
+ end
63
+
64
+ def readwrite(ptr)
65
+ if sodium_mprotect_readwrite(ptr) == -1
66
+ raise MemoryError, "Memory at address=#{ptr.address} is not secured with #{self}.malloc", caller
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ require 'ffi'
2
+
3
+ module Sodium
4
+ class Buffer < FFI::MemoryPointer
5
+ def to_bytes
6
+ read_bytes(size)
7
+ end
8
+
9
+ alias_method :to_str, :to_bytes
10
+ end
11
+ end
@@ -0,0 +1,58 @@
1
+ require_relative '../sodium'
2
+
3
+ module Sodium
4
+ class SecretBuffer
5
+ extend Forwardable
6
+
7
+ def_delegators :@buffer, :address, :to_i
8
+
9
+ attr_reader :size
10
+
11
+ def initialize(size)
12
+ @size = Utils.get_int(size)
13
+ @buffer = Sodium.malloc(@size)
14
+ setup_finalizer
15
+ end
16
+
17
+ def to_ptr
18
+ @buffer
19
+ end
20
+
21
+ def free
22
+ remove_finalizer
23
+ readwrite
24
+ Sodium.free(@buffer)
25
+ @size = @buffer = nil
26
+ end
27
+
28
+ def noaccess
29
+ Sodium.noaccess(@buffer)
30
+ end
31
+
32
+ def readonly
33
+ Sodium.readonly(@buffer)
34
+ end
35
+
36
+ def readwrite
37
+ Sodium.readwrite(@buffer)
38
+ end
39
+
40
+ private
41
+
42
+ def setup_finalizer
43
+ ObjectSpace.define_finalizer(@buffer, self.class.free(address))
44
+ end
45
+
46
+ def remove_finalizer
47
+ ObjectSpace.undefine_finalizer @buffer
48
+ end
49
+
50
+ def self.free(address)
51
+ ->(obj_id) do
52
+ Sodium.readwrite(FFI::Pointer.new(address))
53
+ Sodium.free(FFI::Pointer.new(address))
54
+ true
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,71 @@
1
+ require_relative '../sodium'
2
+
3
+ module Sodium
4
+ module Utils
5
+
6
+ module_function
7
+
8
+ def check_length(data, length, description)
9
+ if data.is_a?(String) ||data.respond_to?(:bytesize)
10
+ unless data.bytesize == length.to_int
11
+ fail Sodium::LengthError, "Expected a length=#{length.to_int} bytes #{description}, got size=#{data.bytesize} bytes", caller
12
+ end
13
+ elsif data.is_a?(FFI::Pointer) ||data.respond_to?(:size)
14
+ unless data.size == length.to_int
15
+ fail Sodium::LengthError, "Expected a length=#{length.to_int} bytes #{description}, got size=#{data.size} bytes", caller
16
+ end
17
+ else
18
+ fail ArgumentError, "#{description} must be of type String or FFI::Pointer and be length=#{length.to_int} bytes long", caller
19
+ end
20
+ true
21
+ end
22
+
23
+ def get_pointer(ptr)
24
+ if ptr.is_a?(FFI::Pointer)
25
+ ptr
26
+ elsif ptr.respond_to?(:to_ptr)
27
+ ptr.to_ptr
28
+ else
29
+ fail ArgumentError, "#{ptr.class} is not a FFI::Pointer", caller
30
+ end
31
+ end
32
+
33
+ def get_string(string)
34
+ if string.is_a?(String)
35
+ string
36
+ elsif string.respond_to?(:to_str)
37
+ string.to_str
38
+ elsif string.respond_to?(:read_string)
39
+ string.read_string
40
+ else
41
+ fail ArgumentError, "#{string.class} is not a String", caller
42
+ end
43
+ end
44
+
45
+ def get_int(int)
46
+ if int.is_a?(Integer)
47
+ int
48
+ elsif int.respond_to?(:to_int)
49
+ int.to_int
50
+ else
51
+ fail ArgumentError, "#{int.class} is not a Integer", caller
52
+ end
53
+ end
54
+
55
+ def get_size(data)
56
+ if data.is_a?(String) ||data.respond_to?(:bytesize)
57
+ data.bytesize
58
+ elsif data.is_a?(FFI::Pointer) ||data.respond_to?(:size)
59
+ data.size
60
+ else
61
+ fail ArgumentError, "#{data.class} doesn't respond to :bytesize or :size", caller
62
+ end
63
+ end
64
+
65
+ ZERO = "\0".force_encoding(Encoding::ASCII_8BIT).freeze
66
+
67
+ def zeros(n)
68
+ ZERO * n
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,3 @@
1
+ module Sodium
2
+ VERSION = '0.0.1'.freeze
3
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ffi-libsodium
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Hendrik Beskow
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.9.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.9.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ description: libsodium ffi wrapper
42
+ email:
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - README.md
49
+ - lib/crypto/aead/chacha20_poly1305.rb
50
+ - lib/crypto/auth.rb
51
+ - lib/crypto/box.rb
52
+ - lib/crypto/generic_hash.rb
53
+ - lib/crypto/one_time_auth.rb
54
+ - lib/crypto/pw_hash/scrypt_salsa208_sha256.rb
55
+ - lib/crypto/scalar_mult.rb
56
+ - lib/crypto/secret_box.rb
57
+ - lib/crypto/short_hash.rb
58
+ - lib/crypto/sign.rb
59
+ - lib/libsodium.rb
60
+ - lib/random_bytes.rb
61
+ - lib/sodium.rb
62
+ - lib/sodium/buffer.rb
63
+ - lib/sodium/secret_buffer.rb
64
+ - lib/sodium/utils.rb
65
+ - lib/sodium/version.rb
66
+ homepage: https://github.com/Asmod4n/ruby-ffi-libsodium
67
+ licenses:
68
+ - Apache-2.0
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 1.9.3
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.4.1
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: libsodium ffi wrapper
90
+ test_files: []