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.
- 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
|