rbnacl 1.0.0.pre

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