rijndael 0.0.1
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.
- checksums.yaml +7 -0
- data/bin/rijndael +49 -0
- data/lib/rijndael.rb +1 -0
- data/lib/rijndael/base.rb +85 -0
- data/lib/rijndael/deep_decrypt.rb +48 -0
- data/lib/rijndael/version.rb +4 -0
- data/test/test_helper.rb +3 -0
- data/test/test_rijndael.rb +66 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ab1bbc3284ccfa1fc6aa42c955e9ac7a07a87006
|
4
|
+
data.tar.gz: d6c2d3614e14c6532f75d513a012807ccd7e0f5d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 91a5efc5b365d9f1fbb3c3371e5622e3931f2b9cce4e476a50d32992fcc32b7d94512d9748c34f68b20c1db99cbd40939e551fe33c3e8f04ef6f75fd18ddbe79
|
7
|
+
data.tar.gz: f56b57521bc05b136e063a829d64653d33d9c3b5d3650c5d0bf1fe8d70d5d003e6f82854e7973d0a00793c4fac841c0cc9f91a74f0c9dab91d12448b9965d017
|
data/bin/rijndael
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rijndael'
|
4
|
+
require 'yaml'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
options = {
|
8
|
+
crypt: []
|
9
|
+
}
|
10
|
+
|
11
|
+
parser = OptionParser.new do |opts|
|
12
|
+
opts.banner = <<HELP
|
13
|
+
Usage:
|
14
|
+
rijndael -k
|
15
|
+
rijndael (-e 'plain' | -d 'cipher')...
|
16
|
+
rijndael -k key [-e 'plain' | -d 'cipher']...
|
17
|
+
HELP
|
18
|
+
opts.separator 'Options:'
|
19
|
+
opts.on('-k', '--key [KEY]', 'Generate or use key') do |key|
|
20
|
+
options[:key] = key
|
21
|
+
end
|
22
|
+
opts.on('-e', '--encrypt PLAIN', 'Encrypt plain text') do |plain|
|
23
|
+
options[:crypt] << { action: :encrypt, value: plain }
|
24
|
+
end
|
25
|
+
opts.on('-d', '--decrypt CIPHER', 'Decrypt cipher text') do |cipher|
|
26
|
+
options[:crypt] << { action: :decrypt, value: cipher }
|
27
|
+
end
|
28
|
+
opts.on_tail('-h', '--help', 'Print this help') do
|
29
|
+
puts opts
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
end
|
33
|
+
parser.parse!
|
34
|
+
|
35
|
+
if !options.key?(:key) && options[:crypt].empty?
|
36
|
+
puts parser
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
|
40
|
+
if options[:key].nil?
|
41
|
+
options[:key] = Rijndael::Base.generate_key
|
42
|
+
puts "Generated key: #{options[:key]}"
|
43
|
+
end
|
44
|
+
|
45
|
+
rijndael = Rijndael::Base.new(options[:key])
|
46
|
+
|
47
|
+
options[:crypt].each do |crypt|
|
48
|
+
puts rijndael.send(crypt[:action], crypt[:value])
|
49
|
+
end
|
data/lib/rijndael.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rijndael/base'
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'base64'
|
3
|
+
require 'yaml'
|
4
|
+
require 'rijndael/deep_decrypt'
|
5
|
+
|
6
|
+
#:nodoc:
|
7
|
+
module Rijndael
|
8
|
+
CIPHER_PATTERN = %r(^\$([a-zA-Z0-9+/]+={0,2})\$([a-zA-Z0-9+/]+={0,2})$)
|
9
|
+
|
10
|
+
##
|
11
|
+
# Simply encrypt and decrypt strings using Rijndael.
|
12
|
+
#
|
13
|
+
class Base
|
14
|
+
include DeepDecrypt
|
15
|
+
|
16
|
+
##
|
17
|
+
# This constructor sets the de-/encryption key.
|
18
|
+
#
|
19
|
+
# @param key [String] Encryption key.
|
20
|
+
#
|
21
|
+
def initialize(key)
|
22
|
+
@key = key
|
23
|
+
fail ArgumentError, 'Key is empty.' if key.nil? || key.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# This method expects a plain text of arbitrary length and encrypts it.
|
28
|
+
#
|
29
|
+
# @param plain [String] Plain text.
|
30
|
+
#
|
31
|
+
# @return [String] Cipher text.
|
32
|
+
#
|
33
|
+
def encrypt(plain)
|
34
|
+
fail ArgumentError, 'No plain text supplied.' if plain.nil? || plain.empty?
|
35
|
+
|
36
|
+
cipher = self.class.cipher
|
37
|
+
cipher.encrypt
|
38
|
+
cipher.key = Base64.decode64(@key)
|
39
|
+
cipher.iv = iv = cipher.random_iv
|
40
|
+
encrypted = cipher.update(plain)
|
41
|
+
encrypted << cipher.final
|
42
|
+
|
43
|
+
iv = Base64.strict_encode64(iv)
|
44
|
+
encrypted = Base64.strict_encode64(encrypted)
|
45
|
+
|
46
|
+
"$#{iv}$#{encrypted}"
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# This method expects a base64 encoded cipher text and decrypts it.
|
51
|
+
#
|
52
|
+
# @param encrypted [String] Cipher text.
|
53
|
+
#
|
54
|
+
# @return [String] Plain text.
|
55
|
+
#
|
56
|
+
def decrypt(encrypted)
|
57
|
+
fail ArgumentError, 'No cipher text supplied.' if encrypted.nil? || encrypted.empty?
|
58
|
+
|
59
|
+
matches = CIPHER_PATTERN.match(encrypted)
|
60
|
+
|
61
|
+
fail ArgumentError, 'Cipher text has an unsupported format.' if matches.nil?
|
62
|
+
|
63
|
+
cipher = self.class.cipher
|
64
|
+
cipher.decrypt
|
65
|
+
cipher.key = Base64.decode64(@key)
|
66
|
+
cipher.iv = Base64.decode64(matches[1])
|
67
|
+
decrypted = cipher.update(Base64.decode64(matches[2]))
|
68
|
+
|
69
|
+
decrypted << cipher.final
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Generate a random key for encryption.
|
74
|
+
#
|
75
|
+
# @return [String] Encryption key.
|
76
|
+
#
|
77
|
+
def self.generate_key
|
78
|
+
Base64.strict_encode64(cipher.random_key)
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.cipher
|
82
|
+
@cipher ||= OpenSSL::Cipher.new 'aes-256-cbc'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
##
|
2
|
+
# Include DeepDecrypter and implement decrypt(String) to make use of:
|
3
|
+
# - decrypt_str
|
4
|
+
# - decrypt_each
|
5
|
+
# - decrypt_hash
|
6
|
+
# - decrypt_deep
|
7
|
+
#
|
8
|
+
module DeepDecrypt
|
9
|
+
def decrypt_deep(obj)
|
10
|
+
case obj
|
11
|
+
when String
|
12
|
+
decrypt_str(obj)
|
13
|
+
when Array
|
14
|
+
decrypt_each(obj)
|
15
|
+
when Hash
|
16
|
+
decrypt_hash(obj)
|
17
|
+
else
|
18
|
+
obj
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def decrypt_str(str)
|
23
|
+
str = str.dup
|
24
|
+
if str =~ Rijndael::CIPHER_PATTERN
|
25
|
+
decrypt(str)
|
26
|
+
else
|
27
|
+
str
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def decrypt_each(arr)
|
32
|
+
res = arr.class.new
|
33
|
+
arr.each do |v|
|
34
|
+
res << decrypt_deep(v)
|
35
|
+
end
|
36
|
+
|
37
|
+
res
|
38
|
+
end
|
39
|
+
|
40
|
+
def decrypt_hash(hash)
|
41
|
+
res = hash.class.new
|
42
|
+
hash.each do |k, v|
|
43
|
+
res[k] = decrypt_deep(v)
|
44
|
+
end
|
45
|
+
|
46
|
+
res
|
47
|
+
end
|
48
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
# Test Crypt functionality
|
4
|
+
class TestCrypt < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@crypt = Rijndael::Base.new('7xnfakb9k1xKWsoUWUtXhGR9qsG+tkdOXdvKGbRkXGY=')
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_loading_empty_key_should_fail
|
10
|
+
ex = assert_raises ArgumentError do
|
11
|
+
Rijndael::Base.new(nil)
|
12
|
+
end
|
13
|
+
assert_equal 'Key is empty.', ex.message
|
14
|
+
|
15
|
+
ex = assert_raises ArgumentError do
|
16
|
+
Rijndael::Base.new('')
|
17
|
+
end
|
18
|
+
assert_equal 'Key is empty.', ex.message
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_encryption
|
22
|
+
e = @crypt.encrypt('plain text')
|
23
|
+
assert_match Rijndael::CIPHER_PATTERN, e
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_decryption
|
27
|
+
d = @crypt.decrypt('$lCNNFWadM6/QIfbdAWJP/g==$oCUTE1bRE2Z7jNM0bRNs4A==')
|
28
|
+
assert_equal 'plain text', d
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_failing_enryption_should_raise
|
32
|
+
ex = assert_raises ArgumentError do
|
33
|
+
@crypt.decrypt('foobar')
|
34
|
+
end
|
35
|
+
assert_equal 'Cipher text has an unsupported format.', ex.message
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_deep_decryption_str
|
39
|
+
d = @crypt.decrypt_deep('$lCNNFWadM6/QIfbdAWJP/g==$SCzLNbG700CIzFifl9yzeg==')
|
40
|
+
assert_equal 'deep text', d
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_deep_decryption_array
|
44
|
+
d = @crypt.decrypt_deep(%w(plain $lCNNFWadM6/QIfbdAWJP/g==$SCzLNbG700CIzFifl9yzeg== text))
|
45
|
+
assert d.include?('deep text')
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_deep_decryption_hash
|
49
|
+
d = @crypt.decrypt_deep(
|
50
|
+
key: 'value',
|
51
|
+
cipher: '$lCNNFWadM6/QIfbdAWJP/g==$SCzLNbG700CIzFifl9yzeg=='
|
52
|
+
)
|
53
|
+
assert_equal 'deep text', d[:cipher]
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_deep_decryption_complex
|
57
|
+
d = @crypt.decrypt_deep(
|
58
|
+
key: 'value',
|
59
|
+
hash: {
|
60
|
+
array: %w(plain $lCNNFWadM6/QIfbdAWJP/g==$SCzLNbG700CIzFifl9yzeg== text),
|
61
|
+
time: Time.now
|
62
|
+
}
|
63
|
+
)
|
64
|
+
assert d[:hash][:array].include?('deep text')
|
65
|
+
end
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rijndael
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Finn Glöe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '10.4'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '10.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.6'
|
41
|
+
description: Easily encrypt and decrypt strings using AES. Rijndael is a wrapper around
|
42
|
+
OpenSSL::Cipher to abstract to a minimum of needed methods.
|
43
|
+
email: finn.gloee@1und1.de
|
44
|
+
executables:
|
45
|
+
- rijndael
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- bin/rijndael
|
50
|
+
- lib/rijndael.rb
|
51
|
+
- lib/rijndael/base.rb
|
52
|
+
- lib/rijndael/deep_decrypt.rb
|
53
|
+
- lib/rijndael/version.rb
|
54
|
+
- test/test_helper.rb
|
55
|
+
- test/test_rijndael.rb
|
56
|
+
homepage: https://github.com/1and1/rijndael
|
57
|
+
licenses:
|
58
|
+
- GPL v2
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 2.4.6
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: Easily encrypt and decrypt strings using AES.
|
80
|
+
test_files:
|
81
|
+
- test/test_helper.rb
|
82
|
+
- test/test_rijndael.rb
|