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
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Crypto::PublicKey do
|
5
|
+
let(:alicepk) { Crypto::TestVectors[:alice_public] }
|
6
|
+
let(:alicepk_raw) { Crypto::Encoder[:hex].decode(alicepk) }
|
7
|
+
|
8
|
+
subject { Crypto::PublicKey.new(alicepk, :hex) }
|
9
|
+
|
10
|
+
context "new" do
|
11
|
+
it "accepts a valid key" do
|
12
|
+
expect { Crypto::PublicKey.new(alicepk_raw) }.not_to raise_error
|
13
|
+
end
|
14
|
+
it "accepts a valid key in hex" do
|
15
|
+
expect { Crypto::PublicKey.new(alicepk, :hex) }.not_to raise_error
|
16
|
+
end
|
17
|
+
it "rejects a nil key" do
|
18
|
+
expect { Crypto::PublicKey.new(nil) }.to raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
it "rejects a short key" do
|
21
|
+
expect { Crypto::PublicKey.new("short") }.to raise_error(ArgumentError)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "#to_bytes" do
|
26
|
+
it "returns the bytes of the key" do
|
27
|
+
subject.to_bytes.should eq alicepk_raw
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "#to_s" do
|
32
|
+
it "returns the bytes of the key" do
|
33
|
+
subject.to_s.should eq alicepk_raw
|
34
|
+
end
|
35
|
+
it "returns the bytes of the key hex encoded" do
|
36
|
+
subject.to_s(:hex).should eq alicepk
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
include_examples "key equality" do
|
41
|
+
let(:key) { subject }
|
42
|
+
let(:key_bytes) { subject.to_bytes }
|
43
|
+
let(:other_key) { described_class.new(alicepk_raw.succ) }
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Crypto::SigningKey do
|
5
|
+
let(:signing_key) { Crypto::TestVectors[:sign_private] }
|
6
|
+
let(:signing_key_raw) { Crypto::Encoder[:hex].decode(signing_key) }
|
7
|
+
|
8
|
+
let(:message) { Crypto::Encoder[:hex].decode(Crypto::TestVectors[:sign_message]) }
|
9
|
+
let(:signature) { Crypto::TestVectors[:sign_signature] }
|
10
|
+
let(:signature_raw) { Crypto::Encoder[:hex].decode(signature) }
|
11
|
+
|
12
|
+
# NOTE: this implicitly covers testing initialization from bytes
|
13
|
+
subject { described_class.new(signing_key, :hex) }
|
14
|
+
|
15
|
+
it "generates keys" do
|
16
|
+
described_class.generate.should be_a described_class
|
17
|
+
end
|
18
|
+
|
19
|
+
it "signs messages as bytes" do
|
20
|
+
subject.sign(message).should eq signature_raw
|
21
|
+
end
|
22
|
+
|
23
|
+
it "signs messages as hex" do
|
24
|
+
subject.sign(message, :hex).should eq signature
|
25
|
+
end
|
26
|
+
|
27
|
+
it "serializes to hex" do
|
28
|
+
subject.to_s(:hex).should eq signing_key
|
29
|
+
end
|
30
|
+
|
31
|
+
it "serializes to bytes" do
|
32
|
+
subject.to_bytes.should eq signing_key_raw
|
33
|
+
end
|
34
|
+
|
35
|
+
include_examples "key equality" do
|
36
|
+
let(:key_bytes) { signing_key_raw }
|
37
|
+
let(:key) { described_class.new(key_bytes) }
|
38
|
+
let(:other_key) { described_class.new("B"*32) }
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
describe Crypto::VerifyKey do
|
3
|
+
let(:signing_key) { Crypto::TestVectors[:sign_private] }
|
4
|
+
let(:verify_key) { Crypto::TestVectors[:sign_public] }
|
5
|
+
let(:verify_key_raw) { Crypto::Encoder[:hex].decode(verify_key) }
|
6
|
+
|
7
|
+
let(:message) { Crypto::Encoder[:hex].decode(Crypto::TestVectors[:sign_message]) }
|
8
|
+
let(:signature) { Crypto::TestVectors[:sign_signature] }
|
9
|
+
let(:signature_raw) { Crypto::Encoder[:hex].decode(signature) }
|
10
|
+
let(:bad_signature) { sig = signature.dup; sig[0] = (sig[0].ord + 1).chr; sig }
|
11
|
+
|
12
|
+
subject { Crypto::SigningKey.new(signing_key, :hex).verify_key }
|
13
|
+
|
14
|
+
it "verifies correct signatures" do
|
15
|
+
subject.verify(message, signature_raw).should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "verifies correct hex signatures" do
|
19
|
+
subject.verify(message, signature, :hex).should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "detects bad signatures" do
|
23
|
+
subject.verify(message, bad_signature, :hex).should be_false
|
24
|
+
end
|
25
|
+
|
26
|
+
it "raises when asked to verify with a bang" do
|
27
|
+
expect { subject.verify!(message, bad_signature, :hex) }.to raise_exception Crypto::BadSignatureError
|
28
|
+
end
|
29
|
+
|
30
|
+
it "serializes to bytes" do
|
31
|
+
subject.to_bytes.should eq verify_key_raw
|
32
|
+
end
|
33
|
+
|
34
|
+
it "serializes to hex" do
|
35
|
+
subject.to_s(:hex).should eq verify_key
|
36
|
+
end
|
37
|
+
|
38
|
+
it "initializes from bytes" do
|
39
|
+
described_class.new(verify_key_raw).to_s(:hex).should eq verify_key
|
40
|
+
end
|
41
|
+
|
42
|
+
it "initializes from hex" do
|
43
|
+
described_class.new(verify_key, :hex).to_s(:hex).should eq verify_key
|
44
|
+
end
|
45
|
+
|
46
|
+
include_examples "key equality" do
|
47
|
+
let(:key_bytes) { verify_key_raw }
|
48
|
+
let(:key) { described_class.new(key_bytes) }
|
49
|
+
let(:other_key) { described_class.new("B"*32) }
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Crypto::Point do
|
5
|
+
let(:alice_private) { Crypto::TestVectors[:alice_private] }
|
6
|
+
let(:alice_public) { Crypto::TestVectors[:alice_public] }
|
7
|
+
|
8
|
+
let(:bob_public) { Crypto::TestVectors[:bob_public] }
|
9
|
+
|
10
|
+
let(:alice_mult_bob) { Crypto::TestVectors[:alice_mult_bob] }
|
11
|
+
|
12
|
+
subject { described_class.new(bob_public, :hex) }
|
13
|
+
|
14
|
+
it "multiplies integers with the base point" do
|
15
|
+
described_class.base.mult(alice_private, :hex).to_s(:hex).should eq alice_public
|
16
|
+
end
|
17
|
+
|
18
|
+
it "multiplies integers with arbitrary points" do
|
19
|
+
described_class.new(bob_public, :hex).mult(alice_private, :hex).to_s(:hex).should eq alice_mult_bob
|
20
|
+
end
|
21
|
+
|
22
|
+
it "serializes to bytes" do
|
23
|
+
subject.to_bytes.should eq Crypto::Encoder[:hex].decode(bob_public)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "serializes to hex" do
|
27
|
+
subject.to_s(:hex).should eq bob_public
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Crypto::RandomNonceBox do
|
5
|
+
let (:secret_key) {
|
6
|
+
[0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,
|
7
|
+
0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89].pack('c*')
|
8
|
+
} # from the nacl distribution
|
9
|
+
let(:secret_box) { Crypto::SecretBox.new(secret_key) }
|
10
|
+
let (:alicepk) { "\x85 \xF0\t\x890\xA7Tt\x8B}\xDC\xB4>\xF7Z\r\xBF:\r&8\x1A\xF4\xEB\xA4\xA9\x8E\xAA\x9BNj" } # from the nacl distribution
|
11
|
+
let (:bobsk) { "]\xAB\b~bJ\x8AKy\xE1\x7F\x8B\x83\x80\x0E\xE6o;\xB1)&\x18\xB6\xFD\x1C/\x8B'\xFF\x88\xE0\xEB" } # from the nacl distribution
|
12
|
+
|
13
|
+
context "instantiation" do
|
14
|
+
it "can be instantiated from an already existing box" do
|
15
|
+
expect { Crypto::RandomNonceBox.new(secret_box) }.not_to raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
it "can be instantiated from a secret key" do
|
19
|
+
Crypto::RandomNonceBox.from_secret_key(secret_key).should be_a Crypto::RandomNonceBox
|
20
|
+
end
|
21
|
+
it "complains on an inappropriate secret key" do
|
22
|
+
expect { Crypto::RandomNonceBox.from_secret_key(nil) }.to raise_error(ArgumentError)
|
23
|
+
end
|
24
|
+
it "can be instantiated from a key-pair" do
|
25
|
+
Crypto::RandomNonceBox.from_keypair(alicepk, bobsk).should be_a Crypto::RandomNonceBox
|
26
|
+
end
|
27
|
+
it "complains on an inappropriate key in the pair" do
|
28
|
+
expect { Crypto::RandomNonceBox.from_keypair(nil, bobsk) }.to raise_error(ArgumentError)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
context "cryptography" do
|
35
|
+
let(:nonce) { "iin\xE9U\xB6+s\xCDb\xBD\xA8u\xFCs\xD6\x82\x19\xE0\x03kz\v7" } # from nacl distribution
|
36
|
+
let(:message) { # from nacl distribution
|
37
|
+
[0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b,
|
38
|
+
0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc,
|
39
|
+
0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29,
|
40
|
+
0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31,
|
41
|
+
0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57,
|
42
|
+
0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde,
|
43
|
+
0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52,
|
44
|
+
0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64,
|
45
|
+
0x5e,0x07,0x05].pack('c*')
|
46
|
+
}
|
47
|
+
let(:ciphertext) { # from nacl distribution
|
48
|
+
[0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
|
49
|
+
0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
|
50
|
+
0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
|
51
|
+
0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
|
52
|
+
0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
|
53
|
+
0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
|
54
|
+
0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
|
55
|
+
0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
|
56
|
+
0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
|
57
|
+
0xe3,0x55,0xa5].pack('c*')
|
58
|
+
}
|
59
|
+
let(:random_box) { Crypto::RandomNonceBox.from_keypair(alicepk, bobsk) }
|
60
|
+
let(:enciphered_message) { random_box.box(message) }
|
61
|
+
let(:enciphered_message_hex) { random_box.box(message, :hex) }
|
62
|
+
|
63
|
+
it "descrypts a message with a 'random' nonce" do
|
64
|
+
random_box.open(nonce+ciphertext).should eql message
|
65
|
+
end
|
66
|
+
|
67
|
+
it "can successfully round-trip a message" do
|
68
|
+
random_box.open(enciphered_message).should eql message
|
69
|
+
end
|
70
|
+
|
71
|
+
it "can encode a ciphertext as hex" do
|
72
|
+
enciphered_message_hex.should match /\A[0-9a-f]+\z/
|
73
|
+
end
|
74
|
+
it "can roundtrip a message as hex" do
|
75
|
+
random_box.open(enciphered_message_hex, :hex).should eql message
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
describe Crypto::Random do
|
3
|
+
it "produces random bytes" do
|
4
|
+
Crypto::Random.random_bytes(16).bytesize.should == 16
|
5
|
+
end
|
6
|
+
it "produces different random bytes" do
|
7
|
+
Crypto::Random.random_bytes(16).should_not == Crypto::Random.random_bytes(16)
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Crypto::SecretBox do
|
5
|
+
let (:key) { Crypto::TestVectors[:secret_key] }
|
6
|
+
|
7
|
+
context "new" do
|
8
|
+
it "accepts strings" do
|
9
|
+
expect { Crypto::SecretBox.new(key, :hex) }.to_not raise_error(Exception)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "raises on a nil key" do
|
13
|
+
expect { Crypto::SecretBox.new(nil) }.to raise_error(Crypto::LengthError, "Secret key was nil \(Expected #{Crypto::NaCl::SECRETKEYBYTES}\)")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "raises on a short key" do
|
17
|
+
expect { Crypto::SecretBox.new("hello") }.to raise_error(Crypto::LengthError, "Secret key was 5 bytes \(Expected #{Crypto::NaCl::SECRETKEYBYTES}\)")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
include_examples "box" do
|
22
|
+
let(:box) { Crypto::SecretBox.new(key, :hex) }
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
describe Crypto::Util do
|
3
|
+
context ".verify32!" do
|
4
|
+
let (:msg) { Crypto::Util.zeros(32) }
|
5
|
+
let (:identical_msg) { Crypto::Util.zeros(32) }
|
6
|
+
let (:other_msg) { Crypto::Util.zeros(31) + "\001" }
|
7
|
+
let (:short_msg) { Crypto::Util.zeros(31) }
|
8
|
+
let (:long_msg) { Crypto::Util.zeros(33) }
|
9
|
+
|
10
|
+
it "confirms identical messages are identical" do
|
11
|
+
Crypto::Util.verify32!(msg, identical_msg).should be true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "confirms non-identical messages are non-identical" do
|
15
|
+
Crypto::Util.verify32!(msg, other_msg).should be false
|
16
|
+
Crypto::Util.verify32!(other_msg, msg).should be false
|
17
|
+
end
|
18
|
+
|
19
|
+
it "raises descriptively on a short message in position 1" do
|
20
|
+
expect { Crypto::Util.verify32!(short_msg, msg) }.to raise_error(Crypto::LengthError)
|
21
|
+
end
|
22
|
+
it "raises descriptively on a short message in position 2" do
|
23
|
+
expect { Crypto::Util.verify32!(msg, short_msg) }.to raise_error(Crypto::LengthError)
|
24
|
+
end
|
25
|
+
it "raises descriptively on a long message in position 1" do
|
26
|
+
expect { Crypto::Util.verify32!(long_msg, msg) }.to raise_error(Crypto::LengthError)
|
27
|
+
end
|
28
|
+
it "raises descriptively on a long message in position 2" do
|
29
|
+
expect { Crypto::Util.verify32!(msg, long_msg) }.to raise_error(Crypto::LengthError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context ".verify32" do
|
34
|
+
let (:msg) { Crypto::Util.zeros(32) }
|
35
|
+
let (:identical_msg) { Crypto::Util.zeros(32) }
|
36
|
+
let (:other_msg) { Crypto::Util.zeros(31) + "\001" }
|
37
|
+
let (:short_msg) { Crypto::Util.zeros(31) }
|
38
|
+
let (:long_msg) { Crypto::Util.zeros(33) }
|
39
|
+
|
40
|
+
it "confirms identical messages are identical" do
|
41
|
+
Crypto::Util.verify32(msg, identical_msg).should be true
|
42
|
+
end
|
43
|
+
|
44
|
+
it "confirms non-identical messages are non-identical" do
|
45
|
+
Crypto::Util.verify32(msg, other_msg).should be false
|
46
|
+
Crypto::Util.verify32(other_msg, msg).should be false
|
47
|
+
Crypto::Util.verify32(short_msg, msg).should be false
|
48
|
+
Crypto::Util.verify32(msg, short_msg).should be false
|
49
|
+
Crypto::Util.verify32(long_msg, msg).should be false
|
50
|
+
Crypto::Util.verify32(msg, long_msg).should be false
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
context ".verify16!" do
|
56
|
+
let (:msg) { Crypto::Util.zeros(16) }
|
57
|
+
let (:identical_msg) { Crypto::Util.zeros(16) }
|
58
|
+
let (:other_msg) { Crypto::Util.zeros(15) + "\001" }
|
59
|
+
let (:short_msg) { Crypto::Util.zeros(15) }
|
60
|
+
let (:long_msg) { Crypto::Util.zeros(17) }
|
61
|
+
|
62
|
+
it "confirms identical messages are identical" do
|
63
|
+
Crypto::Util.verify16!(msg, identical_msg).should be true
|
64
|
+
end
|
65
|
+
|
66
|
+
it "confirms non-identical messages are non-identical" do
|
67
|
+
Crypto::Util.verify16!(msg, other_msg).should be false
|
68
|
+
Crypto::Util.verify16!(other_msg, msg).should be false
|
69
|
+
end
|
70
|
+
|
71
|
+
it "raises descriptively on a short message in position 1" do
|
72
|
+
expect { Crypto::Util.verify16!(short_msg, msg) }.to raise_error(Crypto::LengthError)
|
73
|
+
end
|
74
|
+
it "raises descriptively on a short message in position 2" do
|
75
|
+
expect { Crypto::Util.verify16!(msg, short_msg) }.to raise_error(Crypto::LengthError)
|
76
|
+
end
|
77
|
+
it "raises descriptively on a long message in position 1" do
|
78
|
+
expect { Crypto::Util.verify16!(long_msg, msg) }.to raise_error(Crypto::LengthError)
|
79
|
+
end
|
80
|
+
it "raises descriptively on a long message in position 2" do
|
81
|
+
expect { Crypto::Util.verify16!(msg, long_msg) }.to raise_error(Crypto::LengthError)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context ".verify16" do
|
86
|
+
let (:msg) { Crypto::Util.zeros(16) }
|
87
|
+
let (:identical_msg) { Crypto::Util.zeros(16) }
|
88
|
+
let (:other_msg) { Crypto::Util.zeros(15) + "\001" }
|
89
|
+
let (:short_msg) { Crypto::Util.zeros(15) }
|
90
|
+
let (:long_msg) { Crypto::Util.zeros(17) }
|
91
|
+
|
92
|
+
it "confirms identical messages are identical" do
|
93
|
+
Crypto::Util.verify16(msg, identical_msg).should be true
|
94
|
+
end
|
95
|
+
|
96
|
+
it "confirms non-identical messages are non-identical" do
|
97
|
+
Crypto::Util.verify16(msg, other_msg).should be false
|
98
|
+
Crypto::Util.verify16(other_msg, msg).should be false
|
99
|
+
Crypto::Util.verify16(short_msg, msg).should be false
|
100
|
+
Crypto::Util.verify16(msg, short_msg).should be false
|
101
|
+
Crypto::Util.verify16(long_msg, msg).should be false
|
102
|
+
Crypto::Util.verify16(msg, long_msg).should be false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
context "check_length" do
|
106
|
+
it "accepts strings of the correct length" do
|
107
|
+
expect { Crypto::Util.check_length("A"*4, 4, "Test String") }.not_to raise_error
|
108
|
+
end
|
109
|
+
it "rejects strings which are too short" do
|
110
|
+
expect { Crypto::Util.check_length("A"*3, 4, "Test String") }.to raise_error(Crypto::LengthError, "Test String was 3 bytes (Expected 4)")
|
111
|
+
end
|
112
|
+
it "rejects strings which are too long" do
|
113
|
+
expect { Crypto::Util.check_length("A"*5, 4, "Test String") }.to raise_error(Crypto::LengthError, "Test String was 5 bytes (Expected 4)")
|
114
|
+
end
|
115
|
+
it "rejects nil strings" do
|
116
|
+
expect { Crypto::Util.check_length(nil, 4, "Test String") }.to raise_error(Crypto::LengthError, "Test String was nil (Expected 4)")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
shared_examples "authenticator" do
|
3
|
+
let (:hex_key) { Crypto::TestVectors[:auth_key] }
|
4
|
+
let (:key) { Crypto::Encoder[:hex].decode(hex_key) }
|
5
|
+
let (:message) { Crypto::Encoder[:hex].decode(Crypto::TestVectors[:auth_message]) }
|
6
|
+
let(:tag) { Crypto::Encoder[:hex].decode(hex_tag) }
|
7
|
+
|
8
|
+
context ".new" do
|
9
|
+
it "accepts a key" do
|
10
|
+
expect { described_class.new(key) }.to_not raise_error(ArgumentError)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "requires a key" do
|
14
|
+
expect { described_class.new }.to raise_error(ArgumentError)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "raises on a nil key" do
|
18
|
+
expect { described_class.new(nil) }.to raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "raises on a key which is too long" do
|
22
|
+
expect { described_class.new("\0"*33) }.to raise_error(ArgumentError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "raises on a key which is too short" do
|
26
|
+
expect { described_class.new("\0"*31) }.to raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context ".auth" do
|
31
|
+
it "produces an authenticator" do
|
32
|
+
described_class.auth(key, message).should eq tag
|
33
|
+
end
|
34
|
+
|
35
|
+
it "raises on a nil key" do
|
36
|
+
expect { described_class.auth(nil, message) }.to raise_error(ArgumentError)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "raises on a key which is too long" do
|
40
|
+
expect { described_class.auth("\0"*33, message) }.to raise_error(ArgumentError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context ".verify" do
|
45
|
+
it "verify an authenticator" do
|
46
|
+
described_class.verify(key, message, tag).should eq true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "raises on a nil key" do
|
50
|
+
expect { described_class.verify(nil, message, tag) }.to raise_error(ArgumentError)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "raises on a key which is too long" do
|
54
|
+
expect { described_class.verify("\0"*33, message, tag) }.to raise_error(ArgumentError)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "fails to validate an invalid authenticator" do
|
58
|
+
described_class.verify(key, message+"\0", tag ).should be false
|
59
|
+
end
|
60
|
+
it "fails to validate a short authenticator" do
|
61
|
+
described_class.verify(key, message, tag[0,tag.bytesize - 2]).should be false
|
62
|
+
end
|
63
|
+
it "fails to validate a long authenticator" do
|
64
|
+
described_class.verify(key, message, tag+"\0").should be false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
context "Instance methods" do
|
70
|
+
let(:authenticator) { described_class.new(key) }
|
71
|
+
|
72
|
+
context "#auth" do
|
73
|
+
it "produces an authenticator" do
|
74
|
+
authenticator.auth(message).should eq tag
|
75
|
+
end
|
76
|
+
|
77
|
+
it "produces a hex encoded authenticator" do
|
78
|
+
authenticator.auth(message, :hex).should eq hex_tag
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "#verify" do
|
83
|
+
context "raw bytes" do
|
84
|
+
it "verifies an authenticator" do
|
85
|
+
authenticator.verify(message, tag).should be true
|
86
|
+
end
|
87
|
+
it "fails to validate an invalid authenticator" do
|
88
|
+
authenticator.verify(tag, message+"\0").should be false
|
89
|
+
end
|
90
|
+
it "fails to validate a short authenticator" do
|
91
|
+
authenticator.verify(tag[0,tag.bytesize - 2], message).should be false
|
92
|
+
end
|
93
|
+
it "fails to validate a long authenticator" do
|
94
|
+
authenticator.verify(tag+"\0", message).should be false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "hex" do
|
99
|
+
it "verifies an hexencoded authenticator" do
|
100
|
+
authenticator.verify(message, hex_tag, :hex).should be true
|
101
|
+
end
|
102
|
+
it "fails to validate an invalid authenticator" do
|
103
|
+
authenticator.verify(message+"\0", hex_tag , :hex).should be false
|
104
|
+
end
|
105
|
+
it "fails to validate a short authenticator" do
|
106
|
+
authenticator.verify( message, hex_tag[0,hex_tag.bytesize - 2], :hex).should be false
|
107
|
+
end
|
108
|
+
it "fails to validate a long authenticator" do
|
109
|
+
authenticator.verify(message, hex_tag+"00", :hex).should be false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|