rbnacl 1.0.0 → 1.1.0

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.
@@ -23,7 +23,7 @@ module Crypto
23
23
  # @return [Crypto::SigningKey] Key which can sign messages
24
24
  def initialize(key, encoding = :raw)
25
25
  key = Encoder[encoding].decode(key)
26
- Util.check_length(key, NaCl::PUBLICKEYBYTES, "key")
26
+ Util.check_length(key, NaCl::ED25519_VERIFYKEY_BYTES, "key")
27
27
 
28
28
  @key = key
29
29
  end
@@ -42,13 +42,13 @@ module Crypto
42
42
  # @return [Boolean] was the signature authentic?
43
43
  def verify(message, signature, signature_encoding = :raw)
44
44
  signature = Encoder[signature_encoding].decode(signature)
45
- Util.check_length(signature, NaCl::SIGNATUREBYTES, "signature")
45
+ Util.check_length(signature, signature_bytes, "signature")
46
46
 
47
47
  sig_and_msg = signature + message
48
48
  buffer = Util.zeros(sig_and_msg.bytesize)
49
49
  buffer_len = Util.zeros(FFI::Type::LONG_LONG.size)
50
50
 
51
- NaCl.crypto_sign_open(buffer, buffer_len, sig_and_msg, sig_and_msg.bytesize, @key)
51
+ NaCl.crypto_sign_ed25519_open(buffer, buffer_len, sig_and_msg, sig_and_msg.bytesize, @key)
52
52
  end
53
53
 
54
54
  # "Dangerous" (but probably safer) verify that raises an exception if a
@@ -72,5 +72,25 @@ module Crypto
72
72
  #
73
73
  # @return [String] raw key as bytes
74
74
  def to_bytes; @key; end
75
+
76
+ # The crypto primitive the VerifyKey class uses for signatures
77
+ #
78
+ # @return [Symbol] The primitive
79
+ def self.primitive; :ed25519; end
80
+
81
+ # The crypto primitive this VerifyKey class uses for signatures
82
+ #
83
+ # @return [Symbol] The primitive
84
+ def primitive; self.class.primitive; end
85
+
86
+ # The size of signatures verified by the VerifyKey class
87
+ #
88
+ # @return [Integer] The number of bytes in a signature
89
+ def self.signature_bytes; NaCl::ED25519_SIGNATUREBYTES; end
90
+
91
+ # The size of signatures verified by the VerifyKey instance
92
+ #
93
+ # @return [Integer] The number of bytes in a signature
94
+ def signature_bytes; NaCl::ED25519_SIGNATUREBYTES; end
75
95
  end
76
96
  end
data/lib/rbnacl/nacl.rb CHANGED
@@ -5,6 +5,11 @@ module Crypto
5
5
  #
6
6
  # And that's all it does, really.
7
7
  #
8
+ # HERE BE DRAGONS!
9
+ #
10
+ # Do **NOT** use constants and methods defined here. If you do find yourself
11
+ # needing to, that is a bug in RbNaCl and should be reported.
12
+ #
8
13
  # @private
9
14
  module NaCl
10
15
  extend FFI::Library
@@ -33,42 +38,46 @@ module Crypto
33
38
  SHA256BYTES = 32
34
39
  wrap_nacl_function :crypto_hash_sha256,
35
40
  :crypto_hash_sha256_ref,
36
- [:pointer, :string, :long_long]
41
+ [:pointer, :pointer, :long_long]
37
42
 
38
43
  SHA512BYTES = 64
39
44
  wrap_nacl_function :crypto_hash_sha512,
40
45
  :crypto_hash_sha512_ref,
41
- [:pointer, :string, :long_long]
46
+ [:pointer, :pointer, :long_long]
42
47
 
43
- PUBLICKEYBYTES = 32
44
- SECRETKEYBYTES = 32
45
- wrap_nacl_function :crypto_box_keypair,
48
+ CURVE25519_XSALSA20_POLY1305_PUBLICKEY_BYTES = 32
49
+ PUBLICKEYBYTES = CURVE25519_XSALSA20_POLY1305_PUBLICKEY_BYTES
50
+ CURVE25519_XSALSA20_POLY1305_SECRETKEY_BYTES = 32
51
+ SECRETKEYBYTES = CURVE25519_XSALSA20_POLY1305_SECRETKEY_BYTES
52
+ wrap_nacl_function :crypto_box_curve25519xsalsa20poly1305_keypair,
46
53
  :crypto_box_curve25519xsalsa20poly1305_ref_keypair,
47
54
  [:pointer, :pointer]
48
55
 
49
- NONCEBYTES = 24
56
+ CURVE25519_XSALSA20_POLY1305_BOX_NONCEBYTES = 24
57
+ NONCEBYTES = CURVE25519_XSALSA20_POLY1305_BOX_NONCEBYTES
50
58
  ZEROBYTES = 32
51
59
  BOXZEROBYTES = 16
52
- BEFORENMBYTES = 32
60
+ CURVE25519_XSALSA20_POLY1305_BOX_BEFORENMBYTES = 32
53
61
 
54
- wrap_nacl_function :crypto_box_beforenm,
62
+ wrap_nacl_function :crypto_box_curve25519_xsalsa20_poly1305_beforenm,
55
63
  :crypto_box_curve25519xsalsa20poly1305_ref_beforenm,
56
64
  [:pointer, :pointer, :pointer]
57
65
 
58
- wrap_nacl_function :crypto_box_afternm,
66
+ wrap_nacl_function :crypto_box_curve25519_xsalsa20_poly1305_afternm,
59
67
  :crypto_box_curve25519xsalsa20poly1305_ref_afternm,
60
68
  [:pointer, :pointer, :long_long, :pointer, :pointer]
61
69
 
62
- wrap_nacl_function :crypto_box_open_afternm,
70
+ wrap_nacl_function :crypto_box_curve25519_xsalsa20_poly1305_open_afternm,
63
71
  :crypto_box_curve25519xsalsa20poly1305_ref_open_afternm,
64
72
  [:pointer, :pointer, :long_long, :pointer, :pointer]
65
73
 
66
- SECRETBOX_KEYBYTES = 32
67
- wrap_nacl_function :crypto_secretbox,
74
+ XSALSA20_POLY1305_SECRETBOX_KEYBYTES = 32
75
+ XSALSA20_POLY1305_SECRETBOX_NONCEBYTES = 24
76
+ wrap_nacl_function :crypto_secretbox_xsalsa20poly1305,
68
77
  :crypto_secretbox_xsalsa20poly1305_ref,
69
78
  [:pointer, :pointer, :long_long, :pointer, :pointer]
70
79
 
71
- wrap_nacl_function :crypto_secretbox_open,
80
+ wrap_nacl_function :crypto_secretbox_xsalsa20poly1305_open,
72
81
  :crypto_secretbox_xsalsa20poly1305_ref_open,
73
82
  [:pointer, :pointer, :long_long, :pointer, :pointer]
74
83
 
@@ -110,22 +119,27 @@ module Crypto
110
119
  :crypto_verify_16_ref,
111
120
  [:pointer, :pointer]
112
121
 
113
- SIGNATUREBYTES = 64
114
- wrap_nacl_function :crypto_sign_seed_keypair,
122
+ ED25519_SIGNATUREBYTES = 64
123
+ SIGNATUREBYTES = ED25519_SIGNATUREBYTES
124
+ ED25519_SIGNINGKEY_BYTES = 64
125
+ ED25519_VERIFYKEY_BYTES = 32
126
+ ED25519_SEED_BYTES = 32
127
+ wrap_nacl_function :crypto_sign_ed25519_seed_keypair,
115
128
  :crypto_sign_ed25519_ref_seed_keypair,
116
129
  [:pointer, :pointer, :pointer]
117
130
 
118
- wrap_nacl_function :crypto_sign,
131
+ wrap_nacl_function :crypto_sign_ed25519,
119
132
  :crypto_sign_ed25519_ref,
120
133
  [:pointer, :pointer, :pointer, :long_long, :pointer]
121
134
 
122
- wrap_nacl_function :crypto_sign_open,
135
+ wrap_nacl_function :crypto_sign_ed25519_open,
123
136
  :crypto_sign_ed25519_ref_open,
124
137
  [:pointer, :pointer, :pointer, :long_long, :pointer]
125
138
 
126
- SCALARBYTES = 32
139
+ ED25519_SCALARBYTES = 32
140
+ SCALARBYTES = ED25519_SCALARBYTES
127
141
 
128
- wrap_nacl_function :crypto_scalarmult,
142
+ wrap_nacl_function :crypto_scalarmult_curve25519,
129
143
  :crypto_scalarmult_curve25519_ref,
130
144
  [:pointer, :pointer, :pointer]
131
145
  end
data/lib/rbnacl/point.rb CHANGED
@@ -18,6 +18,9 @@ module Crypto
18
18
  include KeyComparator
19
19
  include Serializable
20
20
 
21
+ # Number of bytes in a scalar on this curve
22
+ SCALARBYTES = NaCl::ED25519_SCALARBYTES
23
+
21
24
  # Creates a new Point from the given serialization
22
25
  #
23
26
  # @param value [String] 32-byte value representing a group element
@@ -29,7 +32,7 @@ module Crypto
29
32
 
30
33
  # FIXME: really should have a separate constant here for group element size
31
34
  # Group elements and scalars are both 32-bits, but that's for convenience
32
- Util.check_length(@point, NaCl::SCALARBYTES, "group element")
35
+ Util.check_length(@point, SCALARBYTES, "group element")
33
36
  end
34
37
 
35
38
  # Multiply the given integer by this point
@@ -42,10 +45,10 @@ module Crypto
42
45
  # @return [Crypto::Point] Result as a Point object
43
46
  def mult(integer, encoding = :raw)
44
47
  integer = Encoder[encoding].decode(integer)
45
- Util.check_length(integer, NaCl::SCALARBYTES, "integer")
48
+ Util.check_length(integer, SCALARBYTES, "integer")
46
49
 
47
- result = Util.zeros(NaCl::SCALARBYTES)
48
- NaCl.crypto_scalarmult(result, integer, @point)
50
+ result = Util.zeros(SCALARBYTES)
51
+ NaCl.crypto_scalarmult_curve25519(result, integer, @point)
49
52
 
50
53
  self.class.new(result)
51
54
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: binary
2
+ require 'forwardable'
2
3
  module Crypto
3
4
  # The simplest nonce strategy that could possibly work
4
5
  #
@@ -27,7 +28,11 @@ module Crypto
27
28
  # there is no protection against messages being reordered and replayed by an
28
29
  # active adversary.
29
30
  class RandomNonceBox
31
+ extend Forwardable
32
+ def_delegators :@box, :nonce_bytes, :primitive
33
+
30
34
  # the size of the nonce
35
+ # DO NOT USE THIS, use the #nonce_bytes method instead
31
36
  NONCEBYTES = NaCl::NONCEBYTES
32
37
 
33
38
  # Create a new RandomNonceBox
@@ -98,11 +103,11 @@ module Crypto
98
103
 
99
104
  private
100
105
  def generate_nonce
101
- Random.random_bytes(NONCEBYTES)
106
+ Random.random_bytes(nonce_bytes)
102
107
  end
103
108
 
104
109
  def extract_nonce(bytes)
105
- nonce = bytes.slice!(0, NONCEBYTES)
110
+ nonce = bytes.slice!(0, nonce_bytes)
106
111
  [nonce, bytes]
107
112
  end
108
113
  end
@@ -18,7 +18,10 @@ module Crypto
18
18
  # non-repudiatable messages, sign them before or after encryption.
19
19
  class SecretBox
20
20
  # Number of bytes for a secret key
21
- KEYBYTES = NaCl::SECRETBOX_KEYBYTES
21
+ KEYBYTES = NaCl::XSALSA20_POLY1305_SECRETBOX_KEYBYTES
22
+
23
+ # Number of bytes for a nonce
24
+ NONCEBYTES = NaCl::XSALSA20_POLY1305_SECRETBOX_NONCEBYTES
22
25
 
23
26
  # Create a new SecretBox
24
27
  #
@@ -50,11 +53,11 @@ module Crypto
50
53
  #
51
54
  # @return [String] The ciphertext without the nonce prepended (BINARY encoded)
52
55
  def box(nonce, message)
53
- Util.check_length(nonce, Crypto::NaCl::NONCEBYTES, "Nonce")
56
+ Util.check_length(nonce, nonce_bytes, "Nonce")
54
57
  msg = Util.prepend_zeros(NaCl::ZEROBYTES, message)
55
58
  ct = Util.zeros(msg.bytesize)
56
59
 
57
- NaCl.crypto_secretbox(ct, msg, msg.bytesize, nonce, @key) || raise(CryptoError, "Encryption failed")
60
+ NaCl.crypto_secretbox_xsalsa20poly1305(ct, msg, msg.bytesize, nonce, @key) || raise(CryptoError, "Encryption failed")
58
61
  Util.remove_zeros(NaCl::BOXZEROBYTES, ct)
59
62
  end
60
63
  alias encrypt box
@@ -74,13 +77,43 @@ module Crypto
74
77
  #
75
78
  # @return [String] The decrypted message (BINARY encoded)
76
79
  def open(nonce, ciphertext)
77
- Util.check_length(nonce, Crypto::NaCl::NONCEBYTES, "Nonce")
80
+ Util.check_length(nonce, nonce_bytes, "Nonce")
78
81
  ct = Util.prepend_zeros(NaCl::BOXZEROBYTES, ciphertext)
79
82
  message = Util.zeros(ct.bytesize)
80
83
 
81
- NaCl.crypto_secretbox_open(message, ct, ct.bytesize, nonce, @key) || raise(CryptoError, "Decryption failed. Ciphertext failed verification.")
84
+ NaCl.crypto_secretbox_xsalsa20poly1305_open(message, ct, ct.bytesize, nonce, @key) || raise(CryptoError, "Decryption failed. Ciphertext failed verification.")
82
85
  Util.remove_zeros(NaCl::ZEROBYTES, message)
83
86
  end
84
87
  alias decrypt open
88
+
89
+ # The crypto primitive for the SecretBox class
90
+ #
91
+ # @return [Symbol] The primitive used
92
+ def self.primitive; :xsalsa20_poly1305; end
93
+
94
+ # The crypto primitive for the SecretBox instance
95
+ #
96
+ # @return [Symbol] The primitive used
97
+ def primitive; self.class.primitive; end
98
+
99
+ # The nonce bytes for the SecretBox class
100
+ #
101
+ # @return [Integer] The number of bytes in a valid nonce
102
+ def self.nonce_bytes; NONCEBYTES; end
103
+
104
+ # The nonce bytes for the SecretBox instance
105
+ #
106
+ # @return [Integer] The number of bytes in a valid nonce
107
+ def nonce_bytes; NONCEBYTES; end
108
+
109
+ # The key bytes for the SecretBox class
110
+ #
111
+ # @return [Integer] The number of bytes in a valid key
112
+ def self.key_bytes; KEYBYTES; end
113
+
114
+ # The key bytes for the SecretBox instance
115
+ #
116
+ # @return [Integer] The number of bytes in a valid key
117
+ def key_bytes; KEYBYTES; end
85
118
  end
86
119
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: binary
2
2
  module Crypto
3
3
  # The library's version
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
data/rbnacl.gemspec CHANGED
@@ -6,8 +6,8 @@ require 'rbnacl/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "rbnacl"
8
8
  gem.version = Crypto::VERSION
9
- gem.authors = ["Tony Arcieri"]
10
- gem.email = ["tony.arcieri@gmail.com"]
9
+ gem.authors = ["Tony Arcieri", "Jonathan Stott"]
10
+ gem.email = ["tony.arcieri@gmail.com", "jonathan.stott@gmail.com"]
11
11
  gem.description = "Ruby binding to the Networking and Cryptography (NaCl) library"
12
12
  gem.summary = "The Networking and Cryptography (NaCl) library provides a high-level toolkit for building cryptographic systems and protocols"
13
13
  gem.homepage = "https://github.com/cryptosphere/rbnacl"
@@ -2,7 +2,7 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Crypto::Auth::OneTime do
5
- let(:hex_tag) { Crypto::TestVectors[:auth_onetime] }
5
+ let(:hex_tag) { hex_vector :auth_onetime }
6
6
 
7
7
  include_examples "authenticator"
8
8
  end
@@ -2,11 +2,11 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Crypto::Box do
5
- let(:alicepk_hex) { Crypto::TestVectors[:alice_public] }
6
- let(:bobsk_hex) { Crypto::TestVectors[:bob_private] }
5
+ let(:alicepk_hex) { hex_vector :alice_public }
6
+ let(:bobsk_hex) { hex_vector :bob_private }
7
7
 
8
- let(:alicepk) { Crypto::Encoder[:hex].decode(alicepk_hex) }
9
- let(:bobsk) { Crypto::Encoder[:hex].decode(bobsk_hex) }
8
+ let(:alicepk) { hex2bytes(alicepk_hex) }
9
+ let(:bobsk) { hex2bytes(bobsk_hex) }
10
10
  let(:alice_key) { Crypto::PublicKey.new(alicepk) }
11
11
  let(:bob_key) { Crypto::PrivateKey.new(bobsk) }
12
12
 
@@ -20,7 +20,7 @@ describe Crypto::Box do
20
20
  end
21
21
 
22
22
  it "raises on a nil public key" do
23
- expect { Crypto::Box.new(nil, bobsk) }.to raise_error(Crypto::LengthError, /Public key was nil \(Expected 32\)/)
23
+ expect { Crypto::Box.new(nil, bobsk) }.to raise_error(Crypto::LengthError, /Public key was 0 bytes \(Expected 32\)/)
24
24
  end
25
25
 
26
26
  it "raises on an invalid public key" do
@@ -28,7 +28,7 @@ describe Crypto::Box do
28
28
  end
29
29
 
30
30
  it "raises on a nil secret key" do
31
- expect { Crypto::Box.new(alicepk, nil) }.to raise_error(Crypto::LengthError, /Private key was nil \(Expected 32\)/)
31
+ expect { Crypto::Box.new(alicepk, nil) }.to raise_error(Crypto::LengthError, /Private key was 0 bytes \(Expected 32\)/)
32
32
  end
33
33
 
34
34
  it "raises on an invalid secret key" do
@@ -3,8 +3,8 @@ require 'spec_helper'
3
3
 
4
4
  describe Crypto::Hash do
5
5
  context "sha256" do
6
- let(:reference_string) { hex2bytes Crypto::TestVectors[:sha256_message] }
7
- let(:reference_string_hash) { hex2bytes Crypto::TestVectors[:sha256_digest] }
6
+ let(:reference_string) { test_vector :sha256_message }
7
+ let(:reference_string_hash) { test_vector :sha256_digest }
8
8
  let(:empty_string_hash) { "\xE3\xB0\xC4B\x98\xFC\x1C\x14\x9A\xFB\xF4\xC8\x99o\xB9$'\xAEA\xE4d\x9B\x93L\xA4\x95\x99\exR\xB8U" }
9
9
  let(:reference_string_hash_hex) { reference_string_hash.unpack('H*').first }
10
10
  let(:empty_string_hash_hex) { empty_string_hash.unpack('H*').first }
@@ -24,6 +24,10 @@ describe Crypto::Hash do
24
24
  it "calculates the correct hash for an empty string and returns it in hex" do
25
25
  Crypto::Hash.sha256("", :hex).should eq empty_string_hash_hex
26
26
  end
27
+
28
+ it "doesn't raise on a null byte" do
29
+ expect { Crypto::Hash.sha256("\0") }.to_not raise_error(/ArgumentError: string contains null byte/)
30
+ end
27
31
  end
28
32
 
29
33
  context "sha512" do
@@ -48,5 +52,9 @@ describe Crypto::Hash do
48
52
  it "calculates the correct hash for an empty string and returns it in hex" do
49
53
  Crypto::Hash.sha512("", :hex).should eq empty_string_hash_hex
50
54
  end
55
+
56
+ it "doesn't raise on a null byte" do
57
+ expect { Crypto::Hash.sha512("\0") }.to_not raise_error(/ArgumentError: string contains null byte/)
58
+ end
51
59
  end
52
60
  end
@@ -2,7 +2,7 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Crypto::HMAC::SHA256 do
5
- let(:hex_tag) { Crypto::TestVectors[:auth_hmacsha256] }
5
+ let(:hex_tag) { hex_vector :auth_hmacsha256 }
6
6
 
7
7
  include_examples "authenticator"
8
8
  end
@@ -2,7 +2,7 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Crypto::HMAC::SHA512256 do
5
- let(:hex_tag) { Crypto::TestVectors[:auth_hmacsha512256] }
5
+ let(:hex_tag) { hex_vector :auth_hmacsha512256 }
6
6
 
7
7
  include_examples "authenticator"
8
8
  end
@@ -2,12 +2,12 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Crypto::PrivateKey do
5
- let(:bobsk) { Crypto::TestVectors[:bob_private] }
6
- let(:bobsk_raw) { Crypto::Encoder[:hex].decode(bobsk) }
7
- let(:bobpk) { Crypto::TestVectors[:bob_public] }
8
- let(:bobpk_raw) { Crypto::Encoder[:hex].decode(bobpk) }
5
+ let(:bobsk) { test_vector :bob_private }
6
+ let(:bobsk_hex) { bytes2hex bobsk }
7
+ let(:bobpk) { test_vector :bob_public }
8
+ let(:bobpk_hex) { bytes2hex bobpk }
9
9
 
10
- subject { Crypto::PrivateKey.new(bobsk, :hex) }
10
+ subject { Crypto::PrivateKey.new(bobsk) }
11
11
 
12
12
  context "generate" do
13
13
  let(:secret_key) { Crypto::PrivateKey.generate }
@@ -23,10 +23,10 @@ describe Crypto::PrivateKey do
23
23
 
24
24
  context "new" do
25
25
  it "accepts a valid key" do
26
- expect { Crypto::PrivateKey.new(bobsk_raw) }.not_to raise_error
26
+ expect { Crypto::PrivateKey.new(bobsk) }.not_to raise_error
27
27
  end
28
28
  it "accepts a hex encoded key" do
29
- expect { Crypto::PrivateKey.new(bobsk, :hex) }.not_to raise_error
29
+ expect { Crypto::PrivateKey.new(bobsk_hex, :hex) }.not_to raise_error
30
30
  end
31
31
  it "rejects a nil key" do
32
32
  expect { Crypto::PrivateKey.new(nil) }.to raise_error(ArgumentError)
@@ -41,28 +41,28 @@ describe Crypto::PrivateKey do
41
41
  subject.public_key.should be_a Crypto::PublicKey
42
42
  end
43
43
  it "returns the correct public key" do
44
- subject.public_key.to_s(:hex).should eql bobpk
44
+ subject.public_key.to_s(:hex).should eql bobpk_hex
45
45
  end
46
46
  end
47
47
 
48
48
  context "#to_bytes" do
49
49
  it "returns the bytes of the key" do
50
- subject.to_s(:hex).should eq bobsk
50
+ subject.to_s(:hex).should eq bobsk_hex
51
51
  end
52
52
  end
53
53
 
54
54
  context "#to_s" do
55
55
  it "returns the bytes of the key hex encoded" do
56
- subject.to_s(:hex).should eq bobsk
56
+ subject.to_s(:hex).should eq bobsk_hex
57
57
  end
58
58
  it "returns the raw bytes of the key" do
59
- subject.to_bytes.should eq bobsk_raw
59
+ subject.to_bytes.should eq bobsk
60
60
  end
61
61
  end
62
62
 
63
63
  include_examples "key equality" do
64
64
  let(:key) { subject }
65
65
  let(:key_bytes) { subject.to_bytes }
66
- let(:other_key) { described_class.new(bobpk, :hex) }
66
+ let(:other_key) { described_class.new(bobpk) }
67
67
  end
68
68
  end