salsa20 0.1.0
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/.gitignore +8 -0
- data/CHANGELOG +3 -0
- data/LICENSE +25 -0
- data/README.rdoc +52 -0
- data/Rakefile +21 -0
- data/ext/salsa20_ext/ecrypt-config.h +272 -0
- data/ext/salsa20_ext/ecrypt-machine.h +46 -0
- data/ext/salsa20_ext/ecrypt-portable.h +303 -0
- data/ext/salsa20_ext/ecrypt-sync.h +279 -0
- data/ext/salsa20_ext/extconf.rb +7 -0
- data/ext/salsa20_ext/salsa20.c +221 -0
- data/ext/salsa20_ext/salsa20_ext.c +87 -0
- data/lib/salsa20.rb +105 -0
- data/salsa20.gemspec +28 -0
- data/test/salsa20_test.rb +140 -0
- metadata +94 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include "ecrypt-sync.h"
|
3
|
+
|
4
|
+
/* Older versions of Ruby (< 1.8.6) need these */
|
5
|
+
#ifndef RSTRING_PTR
|
6
|
+
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
7
|
+
#endif
|
8
|
+
#ifndef RSTRING_LEN
|
9
|
+
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
10
|
+
#endif
|
11
|
+
#ifndef RARRAY_PTR
|
12
|
+
#define RARRAY_PTR(s) (RARRAY(s)->ptr)
|
13
|
+
#endif
|
14
|
+
#ifndef RARRAY_LEN
|
15
|
+
#define RARRAY_LEN(s) (RARRAY(s)->len)
|
16
|
+
#endif
|
17
|
+
|
18
|
+
static VALUE cSalsa20;
|
19
|
+
|
20
|
+
static VALUE rb_salsa20_alloc(VALUE klass) {
|
21
|
+
VALUE obj;
|
22
|
+
ECRYPT_ctx *ctx;
|
23
|
+
|
24
|
+
obj = Data_Make_Struct(klass, ECRYPT_ctx, 0, 0, ctx);
|
25
|
+
return obj;
|
26
|
+
}
|
27
|
+
|
28
|
+
static VALUE rb_salsa20_init_context(VALUE self) {
|
29
|
+
VALUE key, iv;
|
30
|
+
ECRYPT_ctx *ctx;
|
31
|
+
|
32
|
+
Data_Get_Struct(self, ECRYPT_ctx, ctx);
|
33
|
+
key = rb_iv_get(self, "@key");
|
34
|
+
iv = rb_iv_get(self, "@iv");
|
35
|
+
|
36
|
+
ECRYPT_keysetup(ctx, (const unsigned char*)RSTRING_PTR(key), (unsigned int)RSTRING_LEN(key) * 8, 64);
|
37
|
+
ECRYPT_ivsetup(ctx, (const unsigned char*)RSTRING_PTR(iv));
|
38
|
+
|
39
|
+
return self;
|
40
|
+
}
|
41
|
+
|
42
|
+
static VALUE rb_salsa20_encrypt_or_decrypt(int argc, VALUE * argv, VALUE self) {
|
43
|
+
VALUE input, output;
|
44
|
+
ECRYPT_ctx *ctx;
|
45
|
+
|
46
|
+
Data_Get_Struct(self, ECRYPT_ctx, ctx);
|
47
|
+
|
48
|
+
rb_scan_args(argc, argv, "1", &input);
|
49
|
+
Check_Type(input, T_STRING);
|
50
|
+
|
51
|
+
output = rb_str_new(0, RSTRING_LEN(input));
|
52
|
+
ECRYPT_encrypt_bytes(ctx, (const unsigned char*)RSTRING_PTR(input), (unsigned char*)RSTRING_PTR(output), (unsigned int)RSTRING_LEN(input));
|
53
|
+
|
54
|
+
return output;
|
55
|
+
}
|
56
|
+
|
57
|
+
static VALUE rb_salsa20_set_cipher_position(int argc, VALUE * argv, VALUE self) {
|
58
|
+
VALUE low_32bits, high_32bits;
|
59
|
+
ECRYPT_ctx *ctx;
|
60
|
+
|
61
|
+
Data_Get_Struct(self, ECRYPT_ctx, ctx);
|
62
|
+
|
63
|
+
rb_scan_args(argc, argv, "2", &low_32bits, &high_32bits);
|
64
|
+
ctx->input[8] = NUM2INT(low_32bits);
|
65
|
+
ctx->input[9] = NUM2INT(high_32bits);
|
66
|
+
|
67
|
+
return Qnil;
|
68
|
+
}
|
69
|
+
|
70
|
+
static VALUE rb_salsa20_get_cipher_position(VALUE self) {
|
71
|
+
ECRYPT_ctx *ctx;
|
72
|
+
|
73
|
+
Data_Get_Struct(self, ECRYPT_ctx, ctx);
|
74
|
+
|
75
|
+
return rb_ull2inum(((unsigned LONG_LONG)(ctx->input[9]) << 32) | (unsigned LONG_LONG)(ctx->input[8]));
|
76
|
+
}
|
77
|
+
|
78
|
+
void Init_salsa20_ext() {
|
79
|
+
cSalsa20 = rb_define_class("Salsa20", rb_cObject);
|
80
|
+
|
81
|
+
rb_define_alloc_func(cSalsa20, rb_salsa20_alloc);
|
82
|
+
|
83
|
+
rb_define_private_method(cSalsa20, "init_context", rb_salsa20_init_context, 0);
|
84
|
+
rb_define_private_method(cSalsa20, "encrypt_or_decrypt", rb_salsa20_encrypt_or_decrypt, -1);
|
85
|
+
rb_define_private_method(cSalsa20, "set_cipher_position", rb_salsa20_set_cipher_position, -1);
|
86
|
+
rb_define_private_method(cSalsa20, "get_cipher_position", rb_salsa20_get_cipher_position, 0);
|
87
|
+
}
|
data/lib/salsa20.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'salsa20_ext'
|
2
|
+
|
3
|
+
# Salsa20 stream cipher engine. Initialize the engine with +key+ and +iv+, and
|
4
|
+
# then call Salsa20#encrypt or Salsa20#decrypt (they are actually identical --
|
5
|
+
# that's how stream ciphers work).
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# encryptor = Salsa20.new(key_str, iv_str)
|
10
|
+
# cipher_text = encryptor.encrypt(plain_text)
|
11
|
+
#
|
12
|
+
class Salsa20
|
13
|
+
|
14
|
+
# Salsa20 engine was initialized withe a key of the wrong length (see Salsa20#new).
|
15
|
+
class InvalidKeyError < StandardError
|
16
|
+
end
|
17
|
+
|
18
|
+
# Salsa20#encrypt was called after a non 64-bytes boundry block
|
19
|
+
class EngineClosedError < StandardError
|
20
|
+
end
|
21
|
+
|
22
|
+
# Salsa20#seek was called with a non 64-bytes boundry position
|
23
|
+
class IllegalSeekError < StandardError
|
24
|
+
end
|
25
|
+
|
26
|
+
# The encryption key
|
27
|
+
attr_reader :key
|
28
|
+
|
29
|
+
# The encryption IV (Initialization Vector) / nonce
|
30
|
+
attr_reader :iv
|
31
|
+
|
32
|
+
# Create a new Salsa20 encryption/decryption engine.
|
33
|
+
#
|
34
|
+
# +key+ is the encryption key and must be exactly 128-bits (16 bytes) or
|
35
|
+
# 256-bits (32 bytes) long
|
36
|
+
#
|
37
|
+
# +iv+ is the encryption IV and must be exactly 64-bits (8 bytes) long
|
38
|
+
#
|
39
|
+
# If +key+ or +iv+ lengths are invalid then a Salsa20::InvalidKeyError
|
40
|
+
# exception is raised.
|
41
|
+
def initialize(key, iv)
|
42
|
+
# do all the possible checks here to make sure the C extension code gets clean variables
|
43
|
+
raise TypeError, "key must be a String" unless key.is_a? String
|
44
|
+
raise TypeError, "iv must be a String" unless iv.is_a? String
|
45
|
+
|
46
|
+
raise InvalidKeyError, "key length must be 16 or 32 bytes" unless key.size == 16 || key.size == 32
|
47
|
+
raise InvalidKeyError, "iv length must be 8 bytes" unless iv.size == 8
|
48
|
+
|
49
|
+
@key = key
|
50
|
+
@iv = iv
|
51
|
+
@closed = false
|
52
|
+
init_context # Implemented in the C extension
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns _true_ if the last encryption was of a non 64-bytes boundry chunk.
|
56
|
+
# This means this instance cannot be further used (subsequent calls to
|
57
|
+
# Salsa20#encrypt or Salsa20#decrypt will raise a Salsa20::EngineClosedError
|
58
|
+
# exception); _false_ if the instance can be further used to encrypt/decrypt
|
59
|
+
# additional chunks.
|
60
|
+
def closed?
|
61
|
+
@closed
|
62
|
+
end
|
63
|
+
|
64
|
+
# Encrypts/decrypts the string +input+. If +input+ length is on 64-bytes
|
65
|
+
# boundry, you may call encrypt (or decrypt) again; once you call it with a
|
66
|
+
# non 64-bytes boundry chunk this must be the final chunk (subsequent calls will
|
67
|
+
# raise a Salsa20::EngineClosedError exception).
|
68
|
+
#
|
69
|
+
# Returns the encrypted/decrypted string, which has the same size as the
|
70
|
+
# input string.
|
71
|
+
def encrypt(input)
|
72
|
+
raise TypeError, "input must be a string" unless input.is_a? String
|
73
|
+
raise EngineClosedError, "instance is closed" if closed?
|
74
|
+
@closed = true if (input.size % 64) != 0
|
75
|
+
encrypt_or_decrypt(input) # Implemented in the C extension
|
76
|
+
end
|
77
|
+
|
78
|
+
alias :decrypt :encrypt
|
79
|
+
|
80
|
+
# Advance the cipher engine into +position+ (given in bytes). This can be
|
81
|
+
# used to start decrypting from the middle of a file, for example.
|
82
|
+
#
|
83
|
+
# Note: +position+ must be on a 64-bytes boundry (otherwise a
|
84
|
+
# Salsa20::IllegalSeekError exception is raised).
|
85
|
+
def seek(position)
|
86
|
+
raise IllegalSeekError, "seek position must be on 64-bytes boundry" unless position % 64 == 0
|
87
|
+
position /= 64
|
88
|
+
set_cipher_position(low_32bits(position), high_32bits(position)) # Implemented in the C extension
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns the current cipher stream position in bytes
|
92
|
+
def position
|
93
|
+
get_cipher_position * 64
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def low_32bits(n)
|
99
|
+
n & 0xffffffff
|
100
|
+
end
|
101
|
+
|
102
|
+
def high_32bits(n)
|
103
|
+
(n >> 32) & 0xffffffff
|
104
|
+
end
|
105
|
+
end
|
data/salsa20.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'salsa20'
|
3
|
+
s.version = '0.1.0'
|
4
|
+
|
5
|
+
s.summary = "Salsa20 stream cipher algorithm."
|
6
|
+
s.description = <<-EOF
|
7
|
+
Salsa20 is a stream cipher algorithm designed by Daniel Bernstein. salsa20-ruby provides
|
8
|
+
a simple Ruby wrapper.
|
9
|
+
EOF
|
10
|
+
|
11
|
+
s.files = `git ls-files`.split("\n")
|
12
|
+
s.require_path = 'lib'
|
13
|
+
|
14
|
+
s.test_files = `git ls-files test`.split("\n")
|
15
|
+
|
16
|
+
s.add_development_dependency 'rdoc'
|
17
|
+
s.add_development_dependency 'rake-compiler'
|
18
|
+
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.rdoc_options += ['--title', 'salsa20', '--main', 'README.rdoc']
|
21
|
+
s.extra_rdoc_files += ['README.rdoc', 'LICENSE', 'CHANGELOG', 'lib/salsa20.rb']
|
22
|
+
|
23
|
+
s.extensions = 'ext/salsa20_ext/extconf.rb'
|
24
|
+
|
25
|
+
s.authors = ["Dov Murik"]
|
26
|
+
s.email = "dov.murik@gmail.com"
|
27
|
+
s.homepage = "https://github.com/dubek/salsa20-ruby"
|
28
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "salsa20"))
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class Salsa20Test < Test::Unit::TestCase
|
5
|
+
def test_salsa20_keystream
|
6
|
+
expected = "@\x8D\x94\xF48f9Z)\e\xBD\xB8?\xCC\xEC\xD6g\xB3;\xC7ev\v\xCA]\xEE\x19I;\xA2<\\^\xCEFQn\x94B{+\x06\xE2\x85\x9F\xEC\xBBp@\xA4\x8F\xD8~\xD3\x12\x197\f\xD7'\x8C\xC8\xEF\xFC"
|
7
|
+
assert_equal expected, Salsa20.new("K"*32, "I"*8).encrypt("\x00"*64)
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_bad_number_of_arguments_for_new_should_raise_exception
|
11
|
+
assert_raise(ArgumentError) { Salsa20.new }
|
12
|
+
assert_raise(ArgumentError) { Salsa20.new("K"*32) }
|
13
|
+
assert_raise(ArgumentError) { Salsa20.new("K"*32, "I"*8, "third") }
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_non_string_arguments_for_new_should_raise_exception
|
17
|
+
assert_raise(TypeError) { Salsa20.new([1,2,3], "I"*8) }
|
18
|
+
assert_raise(TypeError) { Salsa20.new("K"*32, { "a" => "b"}) }
|
19
|
+
assert_raise(TypeError) { Salsa20.new([1,2,3], { "a" => "b"}) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_invalid_key_length_should_raise_exception
|
23
|
+
assert_raise(Salsa20::InvalidKeyError) { Salsa20.new("K"*15, "I"*8) }
|
24
|
+
assert_nothing_raised { Salsa20.new("K"*16, "I"*8) }
|
25
|
+
assert_raise(Salsa20::InvalidKeyError) { Salsa20.new("K"*17, "I"*8) }
|
26
|
+
assert_raise(Salsa20::InvalidKeyError) { Salsa20.new("K"*31, "I"*8) }
|
27
|
+
assert_nothing_raised { Salsa20.new("K"*32, "I"*8) }
|
28
|
+
assert_raise(Salsa20::InvalidKeyError) { Salsa20.new("K"*33, "I"*8) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_invalid_iv_length_should_raise_exception
|
32
|
+
assert_raise(Salsa20::InvalidKeyError) { Salsa20.new("K"*32, "I"*7) }
|
33
|
+
assert_nothing_raised { Salsa20.new("K"*32, "I"*8) }
|
34
|
+
assert_raise(Salsa20::InvalidKeyError) { Salsa20.new("K"*32, "I"*9) }
|
35
|
+
assert_raise(Salsa20::InvalidKeyError) { Salsa20.new("K"*32, "I"*16) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_accessors
|
39
|
+
the_key = "K"*32
|
40
|
+
the_iv = "I"*8
|
41
|
+
encryptor = Salsa20.new(the_key, the_iv)
|
42
|
+
assert_equal the_key, encryptor.key
|
43
|
+
assert_equal the_iv, encryptor.iv
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_encrypt_and_decrypt_with_256_bit_key
|
47
|
+
the_key = "A"*32
|
48
|
+
the_iv = "B"*8
|
49
|
+
plain_text = "the quick brown fox jumped over the lazy dog"
|
50
|
+
encryptor = Salsa20.new(the_key, the_iv)
|
51
|
+
cipher_text = encryptor.encrypt(plain_text)
|
52
|
+
assert_equal plain_text.size, cipher_text.size
|
53
|
+
decryptor = Salsa20.new(the_key, the_iv)
|
54
|
+
assert_equal plain_text, decryptor.decrypt(cipher_text)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_encrypted_encoding_should_be_binary
|
58
|
+
return unless "TEST".respond_to?(:encoding)
|
59
|
+
save_encoding = Encoding.default_external
|
60
|
+
Encoding.default_external = "UTF-8"
|
61
|
+
the_key = "A"*32
|
62
|
+
the_iv = "B"*8
|
63
|
+
plain_text = "the quick brown fox jumped over the lazy dog"
|
64
|
+
encryptor = Salsa20.new(the_key, the_iv)
|
65
|
+
cipher_text = encryptor.encrypt(plain_text)
|
66
|
+
assert_equal Encoding.find("ASCII-8BIT"), cipher_text.encoding
|
67
|
+
assert_equal Encoding.find("BINARY"), cipher_text.encoding
|
68
|
+
Encoding.default_external = save_encoding
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_encrypt_and_decrypt_with_128_bit_key
|
72
|
+
the_key = "C"*16
|
73
|
+
the_iv = "D"*8
|
74
|
+
plain_text = "the quick brown fox jumped over the lazy dog"
|
75
|
+
encryptor = Salsa20.new(the_key, the_iv)
|
76
|
+
cipher_text = encryptor.encrypt(plain_text)
|
77
|
+
assert_equal plain_text.size, cipher_text.size
|
78
|
+
decryptor = Salsa20.new(the_key, the_iv)
|
79
|
+
assert_equal plain_text, decryptor.decrypt(cipher_text)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_multiple_encrypt_and_one_decrypt
|
83
|
+
the_key = "E"*32
|
84
|
+
the_iv = "F"*8
|
85
|
+
plain_text = "the quick brown fox jumped over the lazy dog" * 5
|
86
|
+
parts = [ plain_text[0,64], plain_text[64,64], plain_text[128,64], plain_text[192,64] ]
|
87
|
+
assert_equal plain_text, parts.join
|
88
|
+
encryptor = Salsa20.new(the_key, the_iv)
|
89
|
+
cipher_text = parts.map { |part| encryptor.encrypt(part) }.join
|
90
|
+
assert_equal true, encryptor.closed?
|
91
|
+
assert_equal plain_text.size, cipher_text.size
|
92
|
+
decryptor = Salsa20.new(the_key, the_iv)
|
93
|
+
assert_equal plain_text, decryptor.decrypt(cipher_text)
|
94
|
+
assert_equal true, decryptor.closed?
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_encrypt_after_non_64_bytes_should_raise_exception
|
98
|
+
the_key = "G"*32
|
99
|
+
the_iv = "H"*8
|
100
|
+
part1 = "a"*63
|
101
|
+
part2 = "b"*64
|
102
|
+
encryptor = Salsa20.new(the_key, the_iv)
|
103
|
+
assert_equal false, encryptor.closed?
|
104
|
+
encryptor.encrypt(part1)
|
105
|
+
assert_equal true, encryptor.closed?
|
106
|
+
assert_raise(Salsa20::EngineClosedError) { encryptor.encrypt(part2) }
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_seek
|
110
|
+
the_key = "I"*32
|
111
|
+
the_iv = "J"*8
|
112
|
+
plain_text = "the quick brown fox jumped over the lazy dog" * 5
|
113
|
+
encryptor = Salsa20.new(the_key, the_iv)
|
114
|
+
cipher_text = encryptor.encrypt(plain_text)
|
115
|
+
decryptor = Salsa20.new(the_key, the_iv)
|
116
|
+
assert_equal 0, decryptor.position
|
117
|
+
cipher_text.slice!(0,128)
|
118
|
+
decryptor.seek(128)
|
119
|
+
assert_equal 128, decryptor.position
|
120
|
+
assert_equal plain_text[128..-1], decryptor.decrypt(cipher_text)
|
121
|
+
assert_equal 256, decryptor.position
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_seek_to_non_64_bytes_boundry_should_raise_exception
|
125
|
+
the_key = "K"*32
|
126
|
+
the_iv = "L"*8
|
127
|
+
encryptor = Salsa20.new(the_key, the_iv)
|
128
|
+
assert_raise(Salsa20::IllegalSeekError) { encryptor.seek(65) }
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_seek_and_position_to_large_positions
|
132
|
+
the_key = "M"*32
|
133
|
+
the_iv = "N"*8
|
134
|
+
large_position = 1 << 50
|
135
|
+
encryptor = Salsa20.new(the_key, the_iv)
|
136
|
+
assert_equal 0, encryptor.position
|
137
|
+
encryptor.seek(large_position)
|
138
|
+
assert_equal large_position, encryptor.position
|
139
|
+
end
|
140
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: salsa20
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dov Murik
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-20 00:00:00.000000000 +03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rdoc
|
17
|
+
requirement: &2156666300 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2156666300
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rake-compiler
|
28
|
+
requirement: &2156665860 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *2156665860
|
37
|
+
description: ! " Salsa20 is a stream cipher algorithm designed by Daniel Bernstein.
|
38
|
+
salsa20-ruby provides\n a simple Ruby wrapper.\n"
|
39
|
+
email: dov.murik@gmail.com
|
40
|
+
executables: []
|
41
|
+
extensions:
|
42
|
+
- ext/salsa20_ext/extconf.rb
|
43
|
+
extra_rdoc_files:
|
44
|
+
- README.rdoc
|
45
|
+
- LICENSE
|
46
|
+
- CHANGELOG
|
47
|
+
- lib/salsa20.rb
|
48
|
+
files:
|
49
|
+
- .gitignore
|
50
|
+
- CHANGELOG
|
51
|
+
- LICENSE
|
52
|
+
- README.rdoc
|
53
|
+
- Rakefile
|
54
|
+
- ext/salsa20_ext/ecrypt-config.h
|
55
|
+
- ext/salsa20_ext/ecrypt-machine.h
|
56
|
+
- ext/salsa20_ext/ecrypt-portable.h
|
57
|
+
- ext/salsa20_ext/ecrypt-sync.h
|
58
|
+
- ext/salsa20_ext/extconf.rb
|
59
|
+
- ext/salsa20_ext/salsa20.c
|
60
|
+
- ext/salsa20_ext/salsa20_ext.c
|
61
|
+
- lib/salsa20.rb
|
62
|
+
- salsa20.gemspec
|
63
|
+
- test/salsa20_test.rb
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: https://github.com/dubek/salsa20-ruby
|
66
|
+
licenses: []
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options:
|
69
|
+
- --title
|
70
|
+
- salsa20
|
71
|
+
- --main
|
72
|
+
- README.rdoc
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 1.6.2
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: Salsa20 stream cipher algorithm.
|
93
|
+
test_files:
|
94
|
+
- test/salsa20_test.rb
|