rbnacl 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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