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,56 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'digest/sha2'
|
5
|
+
|
6
|
+
LIBSODIUM_VERSION = "0.2"
|
7
|
+
|
8
|
+
def sh_hidden(command)
|
9
|
+
STDERR.puts("*** Executing: #{command}")
|
10
|
+
output = `#{command}`
|
11
|
+
|
12
|
+
if !$?.success?
|
13
|
+
STDERR.puts "!!! Error executing: #{command}"
|
14
|
+
STDERR.puts output
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
libsodium_tarball = "libsodium-#{LIBSODIUM_VERSION}.tar.gz"
|
20
|
+
|
21
|
+
file libsodium_tarball do
|
22
|
+
sh "curl -O http://download.dnscrypt.org/libsodium/releases/libsodium-#{LIBSODIUM_VERSION}.tar.gz"
|
23
|
+
|
24
|
+
digest = Digest::SHA256.hexdigest(File.read(libsodium_tarball))
|
25
|
+
if digest != "e99a6b69adc080a5acf6b8a49fdc74b61d6f3579b590e85c93446a8325dde100"
|
26
|
+
rm libsodium_tarball
|
27
|
+
raise "#{libsodium_tarball} failed checksum!"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
file "libsodium" => "libsodium-#{LIBSODIUM_VERSION}.tar.gz" do
|
32
|
+
sh "tar xzf libsodium-#{LIBSODIUM_VERSION}.tar.gz"
|
33
|
+
mv "libsodium-#{LIBSODIUM_VERSION}", "libsodium"
|
34
|
+
end
|
35
|
+
|
36
|
+
file "libsodium/Makefile" => "libsodium" do
|
37
|
+
sh_hidden "cd libsodium && ./configure"
|
38
|
+
end
|
39
|
+
|
40
|
+
file "libsodium/src/libsodium/.libs/libsodium.a" => "libsodium/Makefile" do
|
41
|
+
sh_hidden "cd libsodium && make"
|
42
|
+
end
|
43
|
+
|
44
|
+
if `uname` == 'Darwin'
|
45
|
+
libsodium_lib = "libsodium.bundle"
|
46
|
+
else
|
47
|
+
libsodium_lib = "libsodium.so"
|
48
|
+
end
|
49
|
+
|
50
|
+
file "libsodium/src/libsodium/.libs/#{libsodium_lib}" => "libsodium/src/libsodium/.libs/libsodium.a"
|
51
|
+
|
52
|
+
task :build_libsodium => "libsodium/src/libsodium/.libs/#{libsodium_lib}" do
|
53
|
+
$LIBSODIUM_PATH = "libsodium/src/libsodium/.libs/#{libsodium_lib}"
|
54
|
+
end
|
55
|
+
|
56
|
+
CLEAN.add "libsodium", "libsodium-*.tar.gz"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
module Crypto
|
3
|
+
# Functions for random number generation
|
4
|
+
#
|
5
|
+
# This uses the underlying source of random number generation on the OS, so
|
6
|
+
# /dev/urandom on UNIX-like systems, and the MS crypto providor on windows.
|
7
|
+
module Random
|
8
|
+
# Returns a string of random bytes
|
9
|
+
#
|
10
|
+
# @param [Integer] n number of random bytes desired
|
11
|
+
#
|
12
|
+
# @return [String] random bytes.
|
13
|
+
def self.random_bytes(n=32)
|
14
|
+
buf = Crypto::Util.zeros(n)
|
15
|
+
NaCl.random_bytes(buf, n)
|
16
|
+
buf
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
module Crypto
|
3
|
+
# The simplest nonce strategy that could possibly work
|
4
|
+
#
|
5
|
+
# This class implements the simplest possible nonce generation strategy to
|
6
|
+
# wrap a Crypto::Box or Crypto::SecretBox. A 24-byte random nonce is used
|
7
|
+
# for the encryption and is prepended to the message. When it is time to
|
8
|
+
# open the box, the message is split into nonce and ciphertext, and then the
|
9
|
+
# box is decrypted.
|
10
|
+
#
|
11
|
+
# Thanks to the size of the nonce, the chance of a collision is neglible. For
|
12
|
+
# example, after encrypting 2^64 messages, the odds of their having been
|
13
|
+
# repeated nonce is approximately 2^-64. As an additional convenience, the
|
14
|
+
# ciphertexts may be encoded or decoded by any of the encoders implemented in
|
15
|
+
# the library.
|
16
|
+
#
|
17
|
+
# The resulting ciphertexts are 40 bytes longer than the plain text (24 byte
|
18
|
+
# nonce plus a 16 byte authenticator). This might be annoying if you're
|
19
|
+
# encrypting tweets, but for files represents a fairly small overhead.
|
20
|
+
#
|
21
|
+
# Some caveats:
|
22
|
+
#
|
23
|
+
# * If your random source is broken, so is the security of the messages. You
|
24
|
+
# have bigger problems than just this library at that point, but it's worth
|
25
|
+
# saying.
|
26
|
+
# * The confidentiality of your messages is assured with this strategy, but
|
27
|
+
# there is no protection against messages being reordered and replayed by an
|
28
|
+
# active adversary.
|
29
|
+
class RandomNonceBox
|
30
|
+
# the size of the nonce
|
31
|
+
NONCEBYTES = NaCl::NONCEBYTES
|
32
|
+
|
33
|
+
# Create a new RandomNonceBox
|
34
|
+
#
|
35
|
+
# @param box [SecretBox, Box] the SecretBox or Box to use.
|
36
|
+
#
|
37
|
+
# @return [RandomNonceBox] Ready for use
|
38
|
+
def initialize(box)
|
39
|
+
@box = box
|
40
|
+
end
|
41
|
+
|
42
|
+
# Use a secret key to create a RandomNonceBox
|
43
|
+
#
|
44
|
+
# This is a convenience method. It takes a secret key and instantiates a
|
45
|
+
# SecretBox under the hood, then returns the new RandomNonceBox.
|
46
|
+
#
|
47
|
+
# @param secret_key [String] The secret key, 32 bytes long.
|
48
|
+
#
|
49
|
+
# @return [RandomNonceBox] Ready for use
|
50
|
+
def self.from_secret_key(secret_key)
|
51
|
+
new(SecretBox.new(secret_key))
|
52
|
+
end
|
53
|
+
|
54
|
+
# Use a pair of keys to create a RandomNonceBox
|
55
|
+
#
|
56
|
+
# This is a convenience method. It takes a pair of keys and instantiates a
|
57
|
+
# Box under the hood, then returns the new RandomNonceBox.
|
58
|
+
#
|
59
|
+
# @param private_key [PrivateKey, String] The RbNaCl private key, as class or string
|
60
|
+
# @param public_key [PublicKey, String] The RbNaCl public key, as class or string
|
61
|
+
#
|
62
|
+
# @return [RandomNonceBox] Ready for use
|
63
|
+
def self.from_keypair(private_key, public_key)
|
64
|
+
new(Box.new(private_key, public_key))
|
65
|
+
end
|
66
|
+
|
67
|
+
# Encrypts the message with a random nonce
|
68
|
+
#
|
69
|
+
# Encrypts the message with a random nonce, then returns the ciphertext with
|
70
|
+
# the nonce prepended. Optionally encodes the message using an encoder.
|
71
|
+
#
|
72
|
+
# @param message [String] The message to encrypt
|
73
|
+
# @param encoding [Symbol] Optional encoding for the returned ciphertext
|
74
|
+
#
|
75
|
+
# @return [String] The enciphered message
|
76
|
+
def box(message, encoding = :raw)
|
77
|
+
nonce = generate_nonce
|
78
|
+
cipher_text = @box.box(nonce, message)
|
79
|
+
Encoder[encoding].encode(nonce + cipher_text)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Decrypts the ciphertext with a random nonce
|
83
|
+
#
|
84
|
+
# Takes a ciphertext, optionally decodes it, then splits the nonce off the
|
85
|
+
# front and uses this to decrypt. Returns the message.
|
86
|
+
#
|
87
|
+
# @param enciphered_message [String] The message to decrypt.
|
88
|
+
# @param encoding [Symbol] Optional decoding for the returned ciphertext
|
89
|
+
#
|
90
|
+
# @raise [CryptoError] If the message has been tampered with.
|
91
|
+
#
|
92
|
+
# @return [String] The decoded message
|
93
|
+
def open(enciphered_message, encoding = :raw)
|
94
|
+
decoded = Encoder[encoding].decode(enciphered_message)
|
95
|
+
nonce, ciphertext = *extract_nonce(decoded)
|
96
|
+
@box.open(nonce, ciphertext)
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
def generate_nonce
|
101
|
+
Random.random_bytes(NONCEBYTES)
|
102
|
+
end
|
103
|
+
|
104
|
+
def extract_nonce(bytes)
|
105
|
+
nonce = bytes.slice!(0, NONCEBYTES)
|
106
|
+
[nonce, bytes]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
module Crypto
|
3
|
+
# The SecretBox class boxes and unboxes messages
|
4
|
+
#
|
5
|
+
# This class uses the given secret key to encrypt and decrypt messages.
|
6
|
+
#
|
7
|
+
# It is VITALLY important that the nonce is a nonce, i.e. it is a number used
|
8
|
+
# only once for any given pair of keys. If you fail to do this, you
|
9
|
+
# compromise the privacy of the messages encrypted. Give your nonces a
|
10
|
+
# different prefix, or have one side use an odd counter and one an even counter.
|
11
|
+
# Just make sure they are different.
|
12
|
+
#
|
13
|
+
# The ciphertexts generated by this class include a 16-byte authenticator which
|
14
|
+
# is checked as part of the decryption. An invalid authenticator will cause
|
15
|
+
# the unbox function to raise. The authenticator is not a signature. Once
|
16
|
+
# you've looked in the box, you've demonstrated the ability to create
|
17
|
+
# arbitrary valid messages, so messages you send are repudiatable. For
|
18
|
+
# non-repudiatable messages, sign them before or after encryption.
|
19
|
+
class SecretBox
|
20
|
+
# Number of bytes for a secret key
|
21
|
+
KEYBYTES = NaCl::SECRETBOX_KEYBYTES
|
22
|
+
|
23
|
+
# Create a new SecretBox
|
24
|
+
#
|
25
|
+
# Sets up the Box with a secret key fro encrypting and decrypting messages.
|
26
|
+
#
|
27
|
+
# @param key [String] The key to encrypt and decrypt with
|
28
|
+
# @param encoding [Symbol] Parse key from the given encoding
|
29
|
+
#
|
30
|
+
# @raise [Crypto::LengthError] on invalid keys
|
31
|
+
#
|
32
|
+
# @return [Crypto::SecretBox] The new Box, ready to use
|
33
|
+
def initialize(key, encoding = :raw)
|
34
|
+
@key = Encoder[encoding].decode(key) if key
|
35
|
+
Util.check_length(@key, KEYBYTES, "Secret key")
|
36
|
+
end
|
37
|
+
|
38
|
+
# Encrypts a message
|
39
|
+
#
|
40
|
+
# Encrypts the message with the given nonce to the key set up when
|
41
|
+
# initializing the class. Make sure the nonce is unique for any given
|
42
|
+
# key, or you might as well just send plain text.
|
43
|
+
#
|
44
|
+
# This function takes care of the padding required by the NaCL C API.
|
45
|
+
#
|
46
|
+
# @param nonce [String] A 24-byte string containing the nonce.
|
47
|
+
# @param message [String] The message to be encrypted.
|
48
|
+
#
|
49
|
+
# @raise [Crypto::LengthError] If the nonce is not valid
|
50
|
+
#
|
51
|
+
# @return [String] The ciphertext without the nonce prepended (BINARY encoded)
|
52
|
+
def box(nonce, message)
|
53
|
+
Util.check_length(nonce, Crypto::NaCl::NONCEBYTES, "Nonce")
|
54
|
+
msg = Util.prepend_zeros(NaCl::ZEROBYTES, message)
|
55
|
+
ct = Util.zeros(msg.bytesize)
|
56
|
+
|
57
|
+
NaCl.crypto_secretbox(ct, msg, msg.bytesize, nonce, @key) || raise(CryptoError, "Encryption failed")
|
58
|
+
Util.remove_zeros(NaCl::BOXZEROBYTES, ct)
|
59
|
+
end
|
60
|
+
alias encrypt box
|
61
|
+
|
62
|
+
# Decrypts a ciphertext
|
63
|
+
#
|
64
|
+
# Decrypts the ciphertext with the given nonce using the key setup when
|
65
|
+
# initializing the class.
|
66
|
+
#
|
67
|
+
# This function takes care of the padding required by the NaCL C API.
|
68
|
+
#
|
69
|
+
# @param nonce [String] A 24-byte string containing the nonce.
|
70
|
+
# @param ciphertext [String] The message to be decrypted.
|
71
|
+
#
|
72
|
+
# @raise [Crypto::LengthError] If the nonce is not valid
|
73
|
+
# @raise [Crypto::CryptoError] If the ciphertext cannot be authenticated.
|
74
|
+
#
|
75
|
+
# @return [String] The decrypted message (BINARY encoded)
|
76
|
+
def open(nonce, ciphertext)
|
77
|
+
Util.check_length(nonce, Crypto::NaCl::NONCEBYTES, "Nonce")
|
78
|
+
ct = Util.prepend_zeros(NaCl::BOXZEROBYTES, ciphertext)
|
79
|
+
message = Util.zeros(ct.bytesize)
|
80
|
+
|
81
|
+
NaCl.crypto_secretbox_open(message, ct, ct.bytesize, nonce, @key) || raise(CryptoError, "Decryption failed. Ciphertext failed verification.")
|
82
|
+
Util.remove_zeros(NaCl::ZEROBYTES, message)
|
83
|
+
end
|
84
|
+
alias decrypt open
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
start = Time.now if $DEBUG
|
2
|
+
|
3
|
+
module Crypto
|
4
|
+
class SelfTestFailure < Crypto::CryptoError; end
|
5
|
+
|
6
|
+
module SelfTest
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def box_test
|
10
|
+
alicepk = Crypto::PublicKey.new(TestVectors[:alice_public], :hex)
|
11
|
+
bobsk = Crypto::PrivateKey.new(TestVectors[:bob_private], :hex)
|
12
|
+
|
13
|
+
box = Crypto::Box.new(alicepk, bobsk)
|
14
|
+
box_common_test(box)
|
15
|
+
end
|
16
|
+
|
17
|
+
def secret_box_test
|
18
|
+
box = SecretBox.new(TestVectors[:secret_key], :hex)
|
19
|
+
box_common_test(box)
|
20
|
+
end
|
21
|
+
|
22
|
+
def box_common_test(box)
|
23
|
+
nonce = hexdecode_vector :box_nonce
|
24
|
+
message = hexdecode_vector :box_message
|
25
|
+
ciphertext = hexdecode_vector :box_ciphertext
|
26
|
+
|
27
|
+
unless box.encrypt(nonce, message) == ciphertext
|
28
|
+
raise SelfTestFailure, "failed to generate correct ciphertext"
|
29
|
+
end
|
30
|
+
|
31
|
+
unless box.decrypt(nonce, ciphertext) == message
|
32
|
+
raise SelfTestFailure, "failed to decrypt ciphertext correctly"
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
passed = false
|
37
|
+
corrupt_ct = ciphertext.dup
|
38
|
+
corrupt_ct[23] = ' '
|
39
|
+
box.decrypt(nonce, corrupt_ct)
|
40
|
+
rescue CryptoError
|
41
|
+
passed = true
|
42
|
+
ensure
|
43
|
+
passed or raise SelfTestFailure, "failed to detect corrupt ciphertext"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def digital_signature_test
|
48
|
+
signing_key = SigningKey.new(TestVectors[:sign_private], :hex)
|
49
|
+
verify_key = signing_key.verify_key
|
50
|
+
|
51
|
+
unless verify_key.to_s(:hex) == TestVectors[:sign_public]
|
52
|
+
raise SelfTestFailure, "failed to generate verify key correctly"
|
53
|
+
end
|
54
|
+
|
55
|
+
message = hexdecode_vector :sign_message
|
56
|
+
signature = signing_key.sign(message, :hex)
|
57
|
+
|
58
|
+
unless signature == TestVectors[:sign_signature]
|
59
|
+
raise SelfTestFailure, "failed to generate correct signature"
|
60
|
+
end
|
61
|
+
|
62
|
+
unless verify_key.verify(message, signature, :hex)
|
63
|
+
raise SelfTestFailure, "failed to verify a valid signature"
|
64
|
+
end
|
65
|
+
|
66
|
+
bad_signature = signature[0,127] + '0'
|
67
|
+
|
68
|
+
unless verify_key.verify(message, bad_signature, :hex) == false
|
69
|
+
raise SelfTestFailure, "failed to detect an invalid signature"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def sha256_test
|
74
|
+
message = hexdecode_vector :sha256_message
|
75
|
+
digest = hexdecode_vector :sha256_digest
|
76
|
+
|
77
|
+
unless Crypto::Hash.sha256(message) == digest
|
78
|
+
raise SelfTestFailure, "failed to generate a correct SHA256 digest"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def hmac_test(klass, tag)
|
83
|
+
authenticator = klass.new(TestVectors[:auth_key], :hex)
|
84
|
+
|
85
|
+
message = hexdecode_vector :auth_message
|
86
|
+
|
87
|
+
unless authenticator.auth(message, :hex) == TestVectors[tag]
|
88
|
+
raise SelfTestFailure, "#{klass} failed to generate correct authentication tag"
|
89
|
+
end
|
90
|
+
|
91
|
+
unless authenticator.verify(message, TestVectors[tag], :hex)
|
92
|
+
raise SelfTestFailure, "#{klass} failed to verify correct authentication tag"
|
93
|
+
end
|
94
|
+
|
95
|
+
if authenticator.verify(message+' ', TestVectors[tag], :hex)
|
96
|
+
raise SelfTestFailure, "#{klass} failed to detect invalid authentication tag"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def hexdecode(string)
|
101
|
+
Encoder[:hex].decode(string)
|
102
|
+
end
|
103
|
+
|
104
|
+
def hexdecode_vector(name)
|
105
|
+
hexdecode TestVectors[name]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
Crypto::SelfTest.box_test
|
111
|
+
Crypto::SelfTest.secret_box_test
|
112
|
+
Crypto::SelfTest.digital_signature_test
|
113
|
+
Crypto::SelfTest.sha256_test
|
114
|
+
Crypto::SelfTest.hmac_test Crypto::HMAC::SHA256, :auth_hmacsha256
|
115
|
+
Crypto::SelfTest.hmac_test Crypto::HMAC::SHA512256, :auth_hmacsha512256
|
116
|
+
Crypto::SelfTest.hmac_test Crypto::Auth::OneTime, :auth_onetime
|
117
|
+
|
118
|
+
puts "POST Completed in #{Time.now - start} s" if $DEBUG
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
module Crypto
|
3
|
+
# Serialization features shared across all "key-like" classes
|
4
|
+
module Serializable
|
5
|
+
# Return a string representation of this key, possibly encoded into a
|
6
|
+
# given serialization format.
|
7
|
+
#
|
8
|
+
# @param encoding [String] string encoding format in which to encode the key
|
9
|
+
#
|
10
|
+
# @return [String] key encoded in the specified format
|
11
|
+
def to_s(encoding = :raw)
|
12
|
+
Encoder[encoding].encode(to_bytes)
|
13
|
+
end
|
14
|
+
alias_method :to_str, :to_s
|
15
|
+
|
16
|
+
# Inspect this key
|
17
|
+
#
|
18
|
+
# @return [String] a string representing this key
|
19
|
+
def inspect
|
20
|
+
"#<#{self.class}:#{to_s(:hex)[0,8]}>"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
module Crypto
|
3
|
+
# Reference library of test vectors used to verify the software is correct
|
4
|
+
TestVectors = {
|
5
|
+
#
|
6
|
+
# Curve25519 test vectors
|
7
|
+
# Taken from the NaCl distribution
|
8
|
+
#
|
9
|
+
:alice_private => "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
|
10
|
+
:alice_public => "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a",
|
11
|
+
:bob_private => "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb",
|
12
|
+
:bob_public => "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
|
13
|
+
:alice_mult_bob => "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742",
|
14
|
+
|
15
|
+
#
|
16
|
+
# Box test vectors
|
17
|
+
# Taken from the NaCl distribution
|
18
|
+
#
|
19
|
+
:secret_key => "1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389",
|
20
|
+
:box_nonce => "69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37",
|
21
|
+
:box_message => "be075fc53c81f2d5cf141316ebeb0c7b5228c52a4c62cbd44b66849b64244ffc" +
|
22
|
+
"e5ecbaaf33bd751a1ac728d45e6c61296cdc3c01233561f41db66cce314adb31" +
|
23
|
+
"0e3be8250c46f06dceea3a7fa1348057e2f6556ad6b1318a024a838f21af1fde" +
|
24
|
+
"048977eb48f59ffd4924ca1c60902e52f0a089bc76897040e082f93776384864" +
|
25
|
+
"5e0705",
|
26
|
+
|
27
|
+
:box_ciphertext => "f3ffc7703f9400e52a7dfb4b3d3305d98e993b9f48681273c29650ba32fc76ce" +
|
28
|
+
"48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c972" +
|
29
|
+
"71d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae" +
|
30
|
+
"90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b3" +
|
31
|
+
"7973f622a43d14a6599b1f654cb45a74e355a5",
|
32
|
+
|
33
|
+
#
|
34
|
+
# Ed25519 test vectors
|
35
|
+
# Taken from the Python test vectors: http://ed25519.cr.yp.to/python/sign.input
|
36
|
+
#
|
37
|
+
:sign_private => "b18e1d0045995ec3d010c387ccfeb984d783af8fbb0f40fa7db126d889f6dadd",
|
38
|
+
:sign_public => "77f48b59caeda77751ed138b0ec667ff50f8768c25d48309a8f386a2bad187fb",
|
39
|
+
:sign_message => "916c7d1d268fc0e77c1bef238432573c39be577bbea0998936add2b50a653171" +
|
40
|
+
"ce18a542b0b7f96c1691a3be6031522894a8634183eda38798a0c5d5d79fbd01" +
|
41
|
+
"dd04a8646d71873b77b221998a81922d8105f892316369d5224c9983372d2313" +
|
42
|
+
"c6b1f4556ea26ba49d46e8b561e0fc76633ac9766e68e21fba7edca93c4c7460" +
|
43
|
+
"376d7f3ac22ff372c18f613f2ae2e856af40",
|
44
|
+
:sign_signature => "6bd710a368c1249923fc7a1610747403040f0cc30815a00f9ff548a896bbda0b" +
|
45
|
+
"4eb2ca19ebcf917f0f34200a9edbad3901b64ab09cc5ef7b9bcc3c40c0ff7509",
|
46
|
+
|
47
|
+
#
|
48
|
+
# SHA256 test vectors
|
49
|
+
# Taken from the NSRL test vectors: http://www.nsrl.nist.gov/testdata/
|
50
|
+
:sha256_message => "6162636462636465636465666465666765666768666768696768696a68696a6b" +
|
51
|
+
"696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071",
|
52
|
+
:sha256_digest => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
|
53
|
+
|
54
|
+
#
|
55
|
+
# Auth test vectors
|
56
|
+
# Taken from NaCl distribution
|
57
|
+
#
|
58
|
+
:auth_key => "eea6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff880",
|
59
|
+
:auth_message => "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186a" +
|
60
|
+
"c0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738" +
|
61
|
+
"b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da" +
|
62
|
+
"99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74" +
|
63
|
+
"e355a5",
|
64
|
+
:auth_onetime => "f3ffc7703f9400e52a7dfb4b3d3305d9",
|
65
|
+
# self-created (FIXME: find standard test vectors)
|
66
|
+
:auth_hmacsha256 => "7f7b9b707e8790ca8620ff94df5e6533ddc8e994060ce310c9d7de04d44aabc3",
|
67
|
+
:auth_hmacsha512256 => "b2a31b8d4e01afcab2ee545b5caf4e3d212a99d7b3a116a97cec8e83c32e107d"
|
68
|
+
}
|
69
|
+
end
|