rbnacl 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.coveralls.yml +1 -0
- data/.gitignore +19 -0
- data/.rspec +4 -0
- data/.travis.yml +21 -0
- data/.yardopts +1 -0
- data/CHANGES.md +4 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +23 -0
- data/README.md +179 -0
- data/Rakefile +5 -0
- data/images/dragons.png +0 -0
- data/images/ed25519.png +0 -0
- data/images/logo.png +0 -0
- data/lib/rbnacl.rb +46 -0
- data/lib/rbnacl/auth.rb +78 -0
- data/lib/rbnacl/auth/one_time.rb +38 -0
- data/lib/rbnacl/box.rb +141 -0
- data/lib/rbnacl/encoder.rb +44 -0
- data/lib/rbnacl/encoders/base32.rb +33 -0
- data/lib/rbnacl/encoders/base64.rb +30 -0
- data/lib/rbnacl/encoders/hex.rb +30 -0
- data/lib/rbnacl/encoders/raw.rb +12 -0
- data/lib/rbnacl/hash.rb +48 -0
- data/lib/rbnacl/hmac/sha256.rb +32 -0
- data/lib/rbnacl/hmac/sha512256.rb +35 -0
- data/lib/rbnacl/keys/key_comparator.rb +59 -0
- data/lib/rbnacl/keys/private_key.rb +62 -0
- data/lib/rbnacl/keys/public_key.rb +38 -0
- data/lib/rbnacl/keys/signing_key.rb +74 -0
- data/lib/rbnacl/keys/verify_key.rb +76 -0
- data/lib/rbnacl/nacl.rb +132 -0
- data/lib/rbnacl/point.rb +67 -0
- data/lib/rbnacl/rake_tasks.rb +56 -0
- data/lib/rbnacl/random.rb +19 -0
- data/lib/rbnacl/random_nonce_box.rb +109 -0
- data/lib/rbnacl/secret_box.rb +86 -0
- data/lib/rbnacl/self_test.rb +118 -0
- data/lib/rbnacl/serializable.rb +23 -0
- data/lib/rbnacl/test_vectors.rb +69 -0
- data/lib/rbnacl/util.rb +137 -0
- data/lib/rbnacl/version.rb +5 -0
- data/rbnacl.gemspec +28 -0
- data/rbnacl.gpg +30 -0
- data/spec/rbnacl/auth/one_time_spec.rb +8 -0
- data/spec/rbnacl/box_spec.rb +42 -0
- data/spec/rbnacl/encoder_spec.rb +14 -0
- data/spec/rbnacl/encoders/base32_spec.rb +16 -0
- data/spec/rbnacl/encoders/base64_spec.rb +15 -0
- data/spec/rbnacl/encoders/hex_spec.rb +15 -0
- data/spec/rbnacl/hash_spec.rb +52 -0
- data/spec/rbnacl/hmac/sha256_spec.rb +8 -0
- data/spec/rbnacl/hmac/sha512256_spec.rb +8 -0
- data/spec/rbnacl/keys/private_key_spec.rb +68 -0
- data/spec/rbnacl/keys/public_key_spec.rb +45 -0
- data/spec/rbnacl/keys/signing_key_spec.rb +40 -0
- data/spec/rbnacl/keys/verify_key_spec.rb +51 -0
- data/spec/rbnacl/point_spec.rb +29 -0
- data/spec/rbnacl/random_nonce_box_spec.rb +78 -0
- data/spec/rbnacl/random_spec.rb +9 -0
- data/spec/rbnacl/secret_box_spec.rb +24 -0
- data/spec/rbnacl/util_spec.rb +119 -0
- data/spec/shared/authenticator.rb +114 -0
- data/spec/shared/box.rb +51 -0
- data/spec/shared/key_equality.rb +26 -0
- data/spec/spec_helper.rb +14 -0
- data/tasks/ci.rake +11 -0
- data/tasks/rspec.rake +7 -0
- metadata +187 -0
data/lib/rbnacl/util.rb
ADDED
@@ -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
|
+
|
data/rbnacl.gemspec
ADDED
@@ -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
|
data/rbnacl.gpg
ADDED
@@ -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,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,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
|