rbnacl 1.0.0.pre

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.
Files changed (68) hide show
  1. data/.coveralls.yml +1 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +21 -0
  5. data/.yardopts +1 -0
  6. data/CHANGES.md +4 -0
  7. data/Gemfile +9 -0
  8. data/LICENSE.txt +23 -0
  9. data/README.md +179 -0
  10. data/Rakefile +5 -0
  11. data/images/dragons.png +0 -0
  12. data/images/ed25519.png +0 -0
  13. data/images/logo.png +0 -0
  14. data/lib/rbnacl.rb +46 -0
  15. data/lib/rbnacl/auth.rb +78 -0
  16. data/lib/rbnacl/auth/one_time.rb +38 -0
  17. data/lib/rbnacl/box.rb +141 -0
  18. data/lib/rbnacl/encoder.rb +44 -0
  19. data/lib/rbnacl/encoders/base32.rb +33 -0
  20. data/lib/rbnacl/encoders/base64.rb +30 -0
  21. data/lib/rbnacl/encoders/hex.rb +30 -0
  22. data/lib/rbnacl/encoders/raw.rb +12 -0
  23. data/lib/rbnacl/hash.rb +48 -0
  24. data/lib/rbnacl/hmac/sha256.rb +32 -0
  25. data/lib/rbnacl/hmac/sha512256.rb +35 -0
  26. data/lib/rbnacl/keys/key_comparator.rb +59 -0
  27. data/lib/rbnacl/keys/private_key.rb +62 -0
  28. data/lib/rbnacl/keys/public_key.rb +38 -0
  29. data/lib/rbnacl/keys/signing_key.rb +74 -0
  30. data/lib/rbnacl/keys/verify_key.rb +76 -0
  31. data/lib/rbnacl/nacl.rb +132 -0
  32. data/lib/rbnacl/point.rb +67 -0
  33. data/lib/rbnacl/rake_tasks.rb +56 -0
  34. data/lib/rbnacl/random.rb +19 -0
  35. data/lib/rbnacl/random_nonce_box.rb +109 -0
  36. data/lib/rbnacl/secret_box.rb +86 -0
  37. data/lib/rbnacl/self_test.rb +118 -0
  38. data/lib/rbnacl/serializable.rb +23 -0
  39. data/lib/rbnacl/test_vectors.rb +69 -0
  40. data/lib/rbnacl/util.rb +137 -0
  41. data/lib/rbnacl/version.rb +5 -0
  42. data/rbnacl.gemspec +28 -0
  43. data/rbnacl.gpg +30 -0
  44. data/spec/rbnacl/auth/one_time_spec.rb +8 -0
  45. data/spec/rbnacl/box_spec.rb +42 -0
  46. data/spec/rbnacl/encoder_spec.rb +14 -0
  47. data/spec/rbnacl/encoders/base32_spec.rb +16 -0
  48. data/spec/rbnacl/encoders/base64_spec.rb +15 -0
  49. data/spec/rbnacl/encoders/hex_spec.rb +15 -0
  50. data/spec/rbnacl/hash_spec.rb +52 -0
  51. data/spec/rbnacl/hmac/sha256_spec.rb +8 -0
  52. data/spec/rbnacl/hmac/sha512256_spec.rb +8 -0
  53. data/spec/rbnacl/keys/private_key_spec.rb +68 -0
  54. data/spec/rbnacl/keys/public_key_spec.rb +45 -0
  55. data/spec/rbnacl/keys/signing_key_spec.rb +40 -0
  56. data/spec/rbnacl/keys/verify_key_spec.rb +51 -0
  57. data/spec/rbnacl/point_spec.rb +29 -0
  58. data/spec/rbnacl/random_nonce_box_spec.rb +78 -0
  59. data/spec/rbnacl/random_spec.rb +9 -0
  60. data/spec/rbnacl/secret_box_spec.rb +24 -0
  61. data/spec/rbnacl/util_spec.rb +119 -0
  62. data/spec/shared/authenticator.rb +114 -0
  63. data/spec/shared/box.rb +51 -0
  64. data/spec/shared/key_equality.rb +26 -0
  65. data/spec/spec_helper.rb +14 -0
  66. data/tasks/ci.rake +11 -0
  67. data/tasks/rspec.rake +7 -0
  68. metadata +187 -0
@@ -0,0 +1,137 @@
1
+ # encoding: binary
2
+ module Crypto
3
+ # Various utility functions
4
+ module Util
5
+ module_function
6
+ # Returns a string of n zeros
7
+ #
8
+ # Lots of the functions require us to create strings to pass into functions of a specified size.
9
+ #
10
+ # @param [Integer] n the size of the string to make
11
+ #
12
+ # @return [String] A nice collection of zeros
13
+ def zeros(n=32)
14
+ zeros = "\0" * n
15
+ # make sure they're 8-bit zeros, not 7-bit zeros. Otherwise we might get
16
+ # encoding errors later
17
+ zeros.respond_to?(:force_encoding) ? zeros.force_encoding('ASCII-8BIT') : zeros
18
+ end
19
+
20
+ # Prepends a message with zeros
21
+ #
22
+ # Many functions require a string with some zeros prepended.
23
+ #
24
+ # @param [Integer] n The number of zeros to prepend
25
+ # @param [String] message The string to be prepended
26
+ #
27
+ # @return [String] a bunch of zeros
28
+ def prepend_zeros(n, message)
29
+ zeros(n) + message
30
+ end
31
+
32
+ # Remove zeros from the start of a message
33
+ #
34
+ # Many functions require a string with some zeros prepended, then need them removing after. Note, this modifies the passed in string
35
+ #
36
+ # @param [Integer] n The number of zeros to remove
37
+ # @param [String] message The string to be slice
38
+ #
39
+ # @return [String] less a bunch of zeros
40
+ def remove_zeros(n, message)
41
+ message.slice!(n, message.bytesize - n)
42
+ end
43
+
44
+ # Check the length of the passed in string
45
+ #
46
+ # In several places through the codebase we have to be VERY strict with
47
+ # what length of string we accept. This method supports that.
48
+ #
49
+ # @raise [Crypto::LengthError] If the string is not the right length
50
+ #
51
+ # @param string [String] The string to compare
52
+ # @param length [Integer] The desired length
53
+ # @param description [String] Description of the string (used in the error)
54
+ def check_length(string, length, description)
55
+ if string.nil?
56
+ raise LengthError,
57
+ "#{description} was nil (Expected #{length.to_int})",
58
+ caller
59
+ end
60
+
61
+ if string.bytesize != length.to_int
62
+ raise LengthError,
63
+ "#{description} was #{string.bytesize} bytes (Expected #{length.to_int})",
64
+ caller
65
+ end
66
+ true
67
+ end
68
+
69
+
70
+ # Compare two 32 byte strings in constant time
71
+ #
72
+ # This should help to avoid timing attacks for string comparisons in your
73
+ # application. Note that many of the functions (such as HmacSha256#verify)
74
+ # use this method under the hood already.
75
+ #
76
+ # @param [String] one String #1
77
+ # @param [String] two String #2
78
+ #
79
+ # @return [Boolean] Well, are they equal?
80
+ def verify32(one, two)
81
+ return false unless two.bytesize == 32 && one.bytesize == 32
82
+ NaCl.crypto_verify_32(one, two)
83
+ end
84
+
85
+ # Compare two 32 byte strings in constant time
86
+ #
87
+ # This should help to avoid timing attacks for string comparisons in your
88
+ # application. Note that many of the functions (such as HmacSha256#verify)
89
+ # use this method under the hood already.
90
+ #
91
+ # @param [String] one String #1
92
+ # @param [String] two String #2
93
+ #
94
+ # @raise [ArgumentError] If the strings are not equal in length
95
+ #
96
+ # @return [Boolean] Well, are they equal?
97
+ def verify32!(one, two)
98
+ check_length(one, 32, "First message")
99
+ check_length(two, 32, "Second message")
100
+ NaCl.crypto_verify_32(one, two)
101
+ end
102
+
103
+ # Compare two 16 byte strings in constant time
104
+ #
105
+ # This should help to avoid timing attacks for string comparisons in your
106
+ # application. Note that many of the functions (such as OneTime#verify)
107
+ # use this method under the hood already.
108
+ #
109
+ # @param [String] one String #1
110
+ # @param [String] two String #2
111
+ #
112
+ # @return [Boolean] Well, are they equal?
113
+ def verify16(one, two)
114
+ return false unless two.bytesize == 16 && one.bytesize == 16
115
+ NaCl.crypto_verify_16(one, two)
116
+ end
117
+
118
+ # Compare two 16 byte strings in constant time
119
+ #
120
+ # This should help to avoid timing attacks for string comparisons in your
121
+ # application. Note that many of the functions (such as OneTime#verify)
122
+ # use this method under the hood already.
123
+ #
124
+ # @param [String] one String #1
125
+ # @param [String] two String #2
126
+ #
127
+ # @raise [ArgumentError] If the strings are not equal in length
128
+ #
129
+ # @return [Boolean] Well, are they equal?
130
+ def verify16!(one, two)
131
+ check_length(one, 16, "First message")
132
+ check_length(two, 16, "Second message")
133
+ NaCl.crypto_verify_16(one, two)
134
+ end
135
+ end
136
+ end
137
+
@@ -0,0 +1,5 @@
1
+ # encoding: binary
2
+ module Crypto
3
+ # The library's version
4
+ VERSION = "1.0.0.pre"
5
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rbnacl/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "rbnacl"
8
+ gem.version = Crypto::VERSION
9
+ gem.authors = ["Tony Arcieri"]
10
+ gem.email = ["tony.arcieri@gmail.com"]
11
+ gem.description = "Ruby binding to the Networking and Cryptography (NaCl) library"
12
+ gem.summary = "The Networking and Cryptography (NaCl) library provides a high-level toolkit for building cryptographic systems and protocols"
13
+ gem.homepage = "https://github.com/tarcieri/rbnacl"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ if defined? JRUBY_VERSION
21
+ gem.platform = "jruby"
22
+ end
23
+
24
+ gem.add_runtime_dependency 'ffi'
25
+
26
+ gem.add_development_dependency "rake"
27
+ gem.add_development_dependency "rspec"
28
+ end
@@ -0,0 +1,30 @@
1
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
2
+ Version: GnuPG v1.4.12 (Darwin)
3
+
4
+ mQENBFE2gC4BCADG/9ea48mbfT4Odzi6JLXQMt2z4Md6zO52O1w8RvA32hgx+Sm4
5
+ 4amvwMGb44WXQkSCp//X4YWcZ+WAefZDz8VSfsvQ11CLAnnGPuKiItFCkmDCL0iV
6
+ 2PrHQ3oZ8kfd3/f8qKPZI+TcPmJw1ttF/ugcly7zndCQq+17G/nMYNIxltegtfxm
7
+ AHGeuzgfG6r/IbvBrMgvAmV2+0/CnCpuuuIiSqkp9TnBH3rYl2x4ewwGrgp3GrGT
8
+ OLm/qEKNHbQGa8Q+yaHJczTJ5fNxEdVllEAfVhYPuEoBLDm4fjkgGS98nr9+T7pF
9
+ 9M1IfmszfyenWut6RF1lfRrZQD7v02K7XOIXABEBAAG0JVRvbnkgQXJjaWVyaSA8
10
+ dG9ueS5hcmNpZXJpQGdtYWlsLmNvbT6JAT4EEwECACgFAlE2gC4CGwMFCQHhM4AG
11
+ CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJELIQJp27LYeHjwQH/jktme/Uzxhp
12
+ jodHv9iTUbaNi3PSjmNZJAzmtvsJzavrP2EuYomOK2Z0K387HbWPQpRGNxMzF85X
13
+ 71YYRCGCsja6sFFaiVE5EOzbQVAdT0gyE7U/iPImbqtXAH9WdbxqgjrvnECwDsod
14
+ WyzGaanfbcF9E3b+od/CcjSpcsOJkuxZXwrZKxP9ehvy5dobYrLfageXVxJdj1rs
15
+ 4tuD5IsIQnqW3uUzfaAOLS0oh6e4faDV5232Gva/y7j2fs235ceuHGv24iYf2NAE
16
+ c7rfnOpqT2/3ezNwqpNqE1RH2p1LgtmNkOn7z0iyck171WpCNUaDzT2QVMW1sVEQ
17
+ OQzIVvzM6DC5AQ0EUTaALgEIALCnnwjepJiWFYy6iSMDOZ4g6ifxOPdmlQp0SF83
18
+ BqbEuhr19EBb8Z3BTewIeszwiozCrYyE3Z/hXwJX9JcsTd+YlNE93IMXWq0Dvr2u
19
+ YPhXg4z7Ni9geJaCuQVu4R6pGHI9Irw2F/+xBvccS8nf+xzPsqcqZkFnal5ohCR2
20
+ Z4eXUI26La9qq9j5K6SGMemGwt9FKLXDuInOWSWpiztQBpEo66d8LGqvvHGUUTYH
21
+ LEsJzItLFTHOxTySvjt+9bVWgtXl5iLiR+dAL03Yf6J6E+Dzu12ELoq1kI/M6c0f
22
+ cczmhGT9+9PJfqg2A6MjAF5JEQUVa1HlDH9vnfwSc8nm0qUAEQEAAYkBJQQYAQIA
23
+ DwUCUTaALgIbDAUJAeEzgAAKCRCyECaduy2Hh19aB/93WEEPqVAFzo04f8P27KTw
24
+ n+UiVTTxLkEBNbUHqNDBwWZLBUhzDxoEI21OyAxMzJEj80GXyFtLBMO+lbzz8MvI
25
+ IcfLS3zXaeEFO+fofKbfilvzezSzslPTjxFx0He8C/SjggWVIRPfv5hpoyyx4FXW
26
+ a6ZmA5G29O2J85VhZr8EQuykB10K9tIGIgfpuvjfeL8K30rgPGPfwbZP7/U33Yxs
27
+ qwAwsd6Ej98U8TGUr/tTSVztjg7inWwkL84I3DnfedOn4ofVDetDvtjuaJcc16Z5
28
+ QspnbOIn+KGOcdodZQKglj4Esal0W3kg56Du9M5xzmfEB2UeK5aMTL5akoCjs9aK
29
+ =64l+
30
+ -----END PGP PUBLIC KEY BLOCK-----
@@ -0,0 +1,8 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+
4
+ describe Crypto::Auth::OneTime do
5
+ let(:hex_tag) { Crypto::TestVectors[:auth_onetime] }
6
+
7
+ include_examples "authenticator"
8
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+
4
+ describe Crypto::Box do
5
+ let(:alicepk_hex) { Crypto::TestVectors[:alice_public] }
6
+ let(:bobsk_hex) { Crypto::TestVectors[:bob_private] }
7
+
8
+ let(:alicepk) { Crypto::Encoder[:hex].decode(alicepk_hex) }
9
+ let(:bobsk) { Crypto::Encoder[:hex].decode(bobsk_hex) }
10
+ let(:alice_key) { Crypto::PublicKey.new(alicepk) }
11
+ let(:bob_key) { Crypto::PrivateKey.new(bobsk) }
12
+
13
+ context "new" do
14
+ it "accepts strings" do
15
+ expect { Crypto::Box.new(alicepk_hex, bobsk_hex, :hex) }.to_not raise_error(Exception)
16
+ end
17
+
18
+ it "accepts KeyPairs" do
19
+ expect { Crypto::Box.new(alice_key, bob_key) }.to_not raise_error(Exception)
20
+ end
21
+
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\)/)
24
+ end
25
+
26
+ it "raises on an invalid public key" do
27
+ expect { Crypto::Box.new("hello", bobsk) }.to raise_error(Crypto::LengthError, /Public key was 5 bytes \(Expected 32\)/)
28
+ end
29
+
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\)/)
32
+ end
33
+
34
+ it "raises on an invalid secret key" do
35
+ expect { Crypto::Box.new(alicepk, "hello") }.to raise_error(Crypto::LengthError, /Private key was 5 bytes \(Expected 32\)/)
36
+ end
37
+ end
38
+
39
+ include_examples 'box' do
40
+ let(:box) { Crypto::Box.new(alicepk, bobsk) }
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+
4
+ describe Crypto::Encoder do
5
+ it "registers encoders" do
6
+ expect { Crypto::Encoder[:foobar] }.to raise_exception(ArgumentError)
7
+
8
+ class FoobarEncoder < described_class
9
+ register :foobar
10
+ end
11
+
12
+ Crypto::Encoder[:foobar].should be_a FoobarEncoder
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+ require 'rbnacl/encoders/base32'
4
+
5
+ describe Crypto::Encoders::Base32 do
6
+ let(:source) { "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789" }
7
+ let(:base32) { "mfrggzdfmztwq2lknnwg23tpobyxe43uov3ho6dzpiydcmrtgq2tmnzyhfqwey3emvtgo2djnjvwy3lon5yhc4ttor2xm53ypf5damjsgm2dknrxha4wcytdmrswmz3infvgw3dnnzxxa4lson2hk5txpb4xumbrgiztinjwg44ds===" }
8
+
9
+ it "encodes to base32" do
10
+ subject.encode(source).should eq base32
11
+ end
12
+
13
+ it "decodes from base32" do
14
+ subject.decode(base32).should eq source
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+
4
+ describe Crypto::Encoders::Base64 do
5
+ let(:source) { "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789" }
6
+ let(:base64) { "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5" }
7
+
8
+ it "encodes to base64" do
9
+ subject.encode(source).should eq base64
10
+ end
11
+
12
+ it "decodes from base64" do
13
+ subject.decode(base64).should eq source
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+
4
+ describe Crypto::Encoders::Hex do
5
+ let (:bytes) { [0xDE,0xAD,0xBE,0xEF].pack('c*') }
6
+ let (:hex) { "deadbeef" }
7
+
8
+ it "encodes to hex" do
9
+ subject.encode(bytes).should eq hex
10
+ end
11
+
12
+ it "decodes from hex" do
13
+ subject.decode(hex).should eq bytes
14
+ end
15
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+
4
+ describe Crypto::Hash do
5
+ context "sha256" do
6
+ let(:reference_string) { hex2bytes Crypto::TestVectors[:sha256_message] }
7
+ let(:reference_string_hash) { hex2bytes Crypto::TestVectors[:sha256_digest] }
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
+ let(:reference_string_hash_hex) { reference_string_hash.unpack('H*').first }
10
+ let(:empty_string_hash_hex) { empty_string_hash.unpack('H*').first }
11
+
12
+ it "calculates the correct hash for a reference string" do
13
+ Crypto::Hash.sha256(reference_string).should eq reference_string_hash
14
+ end
15
+
16
+ it "calculates the correct hash for an empty string" do
17
+ Crypto::Hash.sha256("").should eq empty_string_hash
18
+ end
19
+
20
+ it "calculates the correct hash for a reference string and returns it in hex" do
21
+ Crypto::Hash.sha256(reference_string, :hex).should eq reference_string_hash_hex
22
+ end
23
+
24
+ it "calculates the correct hash for an empty string and returns it in hex" do
25
+ Crypto::Hash.sha256("", :hex).should eq empty_string_hash_hex
26
+ end
27
+ end
28
+
29
+ context "sha512" do
30
+ let(:reference_string) { "The quick brown fox jumps over the lazy dog." }
31
+ let(:reference_string_hash) { "\x91\xEA\x12E\xF2\rF\xAE\x9A\x03z\x98\x9FT\xF1\xF7\x90\xF0\xA4v\a\xEE\xB8\xA1M\x12\x89\f\xEAw\xA1\xBB\xC6\xC7\xED\x9C\xF2\x05\xE6{\x7F+\x8F\xD4\xC7\xDF\xD3\xA7\xA8a~E\xF3\xC4c\xD4\x81\xC7\xE5\x86\xC3\x9A\xC1\xED" }
32
+ let(:empty_string_hash) { "\xCF\x83\xE15~\xEF\xB8\xBD\xF1T(P\xD6m\x80\a\xD6 \xE4\x05\vW\x15\xDC\x83\xF4\xA9!\xD3l\xE9\xCEG\xD0\xD1<]\x85\xF2\xB0\xFF\x83\x18\xD2\x87~\xEC/c\xB91\xBDGAz\x81\xA582z\xF9'\xDA>" }
33
+ let(:reference_string_hash_hex) { reference_string_hash.unpack('H*').first }
34
+ let(:empty_string_hash_hex) { empty_string_hash.unpack('H*').first }
35
+
36
+ it "calculates the correct hash for a reference string" do
37
+ Crypto::Hash.sha512(reference_string).should eq reference_string_hash
38
+ end
39
+
40
+ it "calculates the correct hash for an empty string" do
41
+ Crypto::Hash.sha512("").should eq empty_string_hash
42
+ end
43
+
44
+ it "calculates the correct hash for a reference string and returns it in hex" do
45
+ Crypto::Hash.sha512(reference_string, :hex).should eq reference_string_hash_hex
46
+ end
47
+
48
+ it "calculates the correct hash for an empty string and returns it in hex" do
49
+ Crypto::Hash.sha512("", :hex).should eq empty_string_hash_hex
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+
4
+ describe Crypto::HMAC::SHA256 do
5
+ let(:hex_tag) { Crypto::TestVectors[:auth_hmacsha256] }
6
+
7
+ include_examples "authenticator"
8
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+
4
+ describe Crypto::HMAC::SHA512256 do
5
+ let(:hex_tag) { Crypto::TestVectors[:auth_hmacsha512256] }
6
+
7
+ include_examples "authenticator"
8
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: binary
2
+ require 'spec_helper'
3
+
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) }
9
+
10
+ subject { Crypto::PrivateKey.new(bobsk, :hex) }
11
+
12
+ context "generate" do
13
+ let(:secret_key) { Crypto::PrivateKey.generate }
14
+
15
+ it "returns a secret key" do
16
+ secret_key.should be_a Crypto::PrivateKey
17
+ end
18
+
19
+ it "has the public key also set" do
20
+ secret_key.public_key.should be_a Crypto::PublicKey
21
+ end
22
+ end
23
+
24
+ context "new" do
25
+ it "accepts a valid key" do
26
+ expect { Crypto::PrivateKey.new(bobsk_raw) }.not_to raise_error
27
+ end
28
+ it "accepts a hex encoded key" do
29
+ expect { Crypto::PrivateKey.new(bobsk, :hex) }.not_to raise_error
30
+ end
31
+ it "rejects a nil key" do
32
+ expect { Crypto::PrivateKey.new(nil) }.to raise_error(ArgumentError)
33
+ end
34
+ it "rejects a short key" do
35
+ expect { Crypto::PrivateKey.new("short") }.to raise_error(ArgumentError)
36
+ end
37
+ end
38
+
39
+ context "public_key" do
40
+ it "returns a public key" do
41
+ subject.public_key.should be_a Crypto::PublicKey
42
+ end
43
+ it "returns the correct public key" do
44
+ subject.public_key.to_s(:hex).should eql bobpk
45
+ end
46
+ end
47
+
48
+ context "#to_bytes" do
49
+ it "returns the bytes of the key" do
50
+ subject.to_s(:hex).should eq bobsk
51
+ end
52
+ end
53
+
54
+ context "#to_s" do
55
+ it "returns the bytes of the key hex encoded" do
56
+ subject.to_s(:hex).should eq bobsk
57
+ end
58
+ it "returns the raw bytes of the key" do
59
+ subject.to_bytes.should eq bobsk_raw
60
+ end
61
+ end
62
+
63
+ include_examples "key equality" do
64
+ let(:key) { subject }
65
+ let(:key_bytes) { subject.to_bytes }
66
+ let(:other_key) { described_class.new(bobpk, :hex) }
67
+ end
68
+ end