gibberish 1.4.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb91ee54144607b435939ae489177ad3d945c289
4
- data.tar.gz: 77d0ad48cb4b73c17c668551b22bb6174d3dd514
3
+ metadata.gz: 6eca32966c5ac459d70f832120c67175359ab581
4
+ data.tar.gz: 9ea06902e68d9e6c71410e9f6b79ce42642c46d4
5
5
  SHA512:
6
- metadata.gz: 1d74406ff02f4149972d6c43fc87e87074ab6627273dfc2f4469107516a9dc466887704eb783ccf544ded546903e1a1ec3fca1383b63f60dfc56c420e5a7fa97
7
- data.tar.gz: 18888bca02b332aa695ae348025a2609538787e1c9e8f9fad27efa80c347dee1f20b4ff51d54fc75a563086a90d7f1783922571c289f389e21f759a5dc002c4b
6
+ metadata.gz: 036a7424a015301eb8df8f95bdfa50d924aa9aa0589667d6795bd01ca5db791572a9f0b5015d357ec1cd61d3cbe09b9686d28b0ff9ed0d46c7276d231b13943e
7
+ data.tar.gz: 119793a0005f102286c3a79b389e539952b4015c739b5269862028a8fc4e4656d32bbb31c1cb277e0f4b6ae8b6b278819604c97ad64f3ff5f60e83737a390488
data/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
+ .yardoc*
1
2
  *.gem
2
3
  Gemfile.lock
4
+ /doc
data/.travis.yml CHANGED
@@ -2,4 +2,3 @@ language: ruby
2
2
  rvm:
3
3
  - 2.1.0
4
4
  - 2.0.0
5
- - 1.9.3
data/CHANGELOG.mdown CHANGED
@@ -1,3 +1,14 @@
1
+ ### v2.0.0
2
+ * Breaking changes to default AES mode
3
+ - Moving to [SJCL](http://bitwiseshiftleft.github.io/sjcl/) compatible AES
4
+ - AES now uses only authenticated modes ("GCM" and "CCM")
5
+ - Deprecating streaming and file AES encryption. This would be better handled
6
+ by another library. Gibberish will focus on compatibility with Javascript/Browser encryption.
7
+ - 1.x CBC encryption/decryption is still available. You can still encrypt and decrypt
8
+ older Gibberish generated AES ciphertexts, but you must call it explicitly
9
+ * Breaking change to HMAC - User must explicitly choose a digest. No longer defaults to SHA1
10
+ * Deprecating Ruby 1.9.3 since its OpenSSL bindings do not allow for authenticated modes
11
+
1
12
  ### v1.4.0
2
13
  * Fix deprecation. Support for 1.8.7 is deprecated, so bumping minor rev [PR #15](https://github.com/mdp/gibberish/pull/15)
3
14
 
data/Gemfile CHANGED
@@ -1,5 +1,8 @@
1
1
  source "http://rubygems.org"
2
2
  gemspec
3
- gem 'minitest'
4
- gem 'mini_shoulda'
5
- gem 'rake'
3
+ group :development, :test do
4
+ gem 'yard'
5
+ gem 'minitest'
6
+ gem 'mini_shoulda'
7
+ gem 'rake'
8
+ end
data/Makefile ADDED
@@ -0,0 +1,16 @@
1
+ all: install test docs
2
+
3
+ install:
4
+ bundle install;
5
+
6
+ test:
7
+ bundle exec rake;
8
+
9
+ benchmark:
10
+ ruby spec/*_benchmark.rb;
11
+
12
+ docs:
13
+ rm -rf doc;
14
+ bundle exec yard;
15
+
16
+ .PHONY: install test docs benchmark
data/README.markdown CHANGED
@@ -1,28 +1,19 @@
1
- # Gibberish - Encryption in Ruby made simple
2
- ![Travis](https://secure.travis-ci.org/mdp/gibberish.png)
1
+ # Gibberish - A ruby encryption library
2
+ [![Travis](https://secure.travis-ci.org/mdp/gibberish.png)](https://travis-ci.org/mdp/gibberish)
3
3
 
4
- ### What
5
- Gibberish is an opinionated cryptography library for Ruby. Its objective is easy but secure
6
- encryption in Ruby.
4
+ *NOTICE: Breaking Changes in 2.0*
7
5
 
8
- ### Why
9
- While OpenSSL is an extremely capable encryption library, it lacks a terse and clean
10
- interface in Ruby.
11
-
12
- ### Goals
13
- - This library should remain easily iteroperable with the OpenSSL command
14
- line interface. Each function will include documentation on how to perform
15
- the same routine via the command line with OpenSSL
16
-
17
- - It should default to a reasonably secure setting, e.g. 256-bit AES, or SHA1 for HMAC
18
- But it should allow the user to specify a stronger setting, within reason.
19
-
20
- - Procedures should be well tested and be compatible with Ruby 1.8.7 and 1.9
6
+ Checkout the [Changelog](CHANGELOG.mdown) for a full list of changes in 2.0
21
7
 
8
+ ## Goals
9
+ - AES encryption should have sensible defaults
10
+ - AES should be interoperable with SJCL for browser based decryption/encryption
11
+ - Simple API for HMAC/Digests
12
+ - Targets more recent versions of Ruby(>=2.0) with better OpenSSL support
22
13
 
23
14
  ## Requirements
24
15
 
25
- Ruby compiled with OpenSSL support
16
+ Ruby 2.0 or later, compiled with OpenSSL support
26
17
 
27
18
  ## Installation
28
19
 
@@ -30,55 +21,49 @@ Ruby compiled with OpenSSL support
30
21
 
31
22
  ## AES
32
23
 
33
- Defaults to 256 bit CBC encryption
24
+ AES encryption with sensible defaults:
34
25
 
35
- cipher = Gibberish::AES.new("p4ssw0rd")
36
- cipher.enc("Some top secret data")
37
- #=> U2FsdGVkX187oKRbgDkUcMKaFfB5RsXQj/X4mc8X3lsUVgwb4+S55LQo6f6N\nIDMX
26
+ - 100,000 iterations of PBKDF2 password hardening
27
+ - GCM mode with authentication
28
+ - Ability to include authenticated data
29
+ - Compatible with [SJCL](http://bitwiseshiftleft.github.io/sjcl/), meaning all ciphertext is decryptable in JS via [SJCL](http://bitwiseshiftleft.github.io/sjcl/)
38
30
 
39
- cipher.dec("U2FsdGVkX187oKRbgDkUcMKaFfB5RsXQj/X4mc8X3lsUVgwb4+S55LQo6f6N\nIDMX")
40
- #=> "Some top secret data"
31
+ ### Encrypting
41
32
 
42
- To encrypt / decrypt a file
33
+ cipher = Gibberish::AES.new('p4ssw0rd')
34
+ cipher.encrypt("some secret text")
35
+ # => Outputs a JSON string containing everything that needs to be saved for future decryption
36
+ # Example:
37
+ # '{"v":1,"adata":"","ks":256,"ct":"ay2varjSFUMUmtvZeh9755GVyCkWHG0/BglJLQ==","ts":96,"mode":"gcm",
38
+ # "cipher":"aes","iter":100000,"iv":"K4ZShCQGL3UZr78y","salt":"diDUzbc9Euo="}'
43
39
 
44
- cipher.encrypt_file("secret.txt", "secret.txt.enc")
40
+ ### Decrypting
45
41
 
46
- cipher.decrypt_file("secret.txt.enc", "secret.txt")
42
+ cipher = Gibberish::AES.new('p4ssw0rd')
43
+ cipher.decrypt('{"v":1,"adata":"","ks":256,"ct":"ay2varjSFUMUmtvZeh9755GVyCkWHG0/BglJLQ==","ts":96,"mode":"gcm","cipher":"aes","iter":100000,"iv":"K4ZShCQGL3UZr78y","salt":"diDUzbc9Euo="}')
44
+ # => "some secret text"
47
45
 
48
- Gibberish AES is fully compatible with default OpenSSL on the command line
46
+ ### Interoperability with SJCL (JavaScript - Browser/Node.js)
49
47
 
50
- echo "U2FsdGVkX187oKRbgDkUcMKaFfB5RsXQj/X4mc8X3lsUVgwb4+S55LQo6f6N\nIDMX\n" | \
51
- openssl enc -d -aes-256-cbc -a -k p4ssw0rd
48
+ AES ciphertext from Gibberish is compatible with [SJCL](http://bitwiseshiftleft.github.io/sjcl/), a JavaScript library which
49
+ works in the browser and Node.js
52
50
 
53
- openssl aes-256-cbc -d -in secret.txt.enc -out secret.txt -k p4ssw0rd
51
+ [See the full docs](http://www.rubydoc.info/github/mdp/gibberish/Gibberish/AES) for information on SJCL interoperability.
54
52
 
55
- [Find out more](http://mdp.github.com/gibberish/Gibberish/AES.html)
53
+ ### Gibberish 1.x Encryption (CBC)
56
54
 
57
- ## RSA
55
+ Prior to Gibberish 2.0, the default encryption mode was CBC. You can still access this
56
+ by calling it explicitly:
58
57
 
59
- k = Gibberish::RSA.generate_keypair(1024)
60
- cipher = Gibberish::RSA.new(k.public_key)
61
- enc = cipher.encrypt("Some data")
62
- # Defaults to Base64 output
63
- #=> "JKm98wKyJljqmpx7kP8ZsdeXiShllEMcRHVnjUjc4ecyYK/doKAkVTLho1Gp\ng697qrljyClF0AcIH+XZmeF/TrqYUuCEUyhOD6OL1bs5dn8vFQefS5KdaC5Y\ndLADvh3mSfE/w/gs4vaf/OtbZNBeSl6ROCZasWTfRewp4n1RDmE=\n"
64
- cipher = Gibberish::RSA.new(k.private_key)
65
- dec = cipher.decrypt(enc)
66
-
67
- [Find out more](http://mdp.github.com/gibberish/Gibberish/RSA.html)
58
+ cipher = Gibberish::AES::CBC.new('p4ssw0rd')
59
+ cipher.encrypt("Some secret text")
68
60
 
69
61
  ## HMAC
70
62
 
71
- Defaults to 128 bit digest and SHA1
72
-
73
- Gibberish::HMAC("key", "some data")
74
- #=> 521677c580722c5c52fa15d978e8656341c4f3c5
75
-
76
- Other digests can be used
63
+ Gibberish::HMAC256("password", "data")
64
+ # => "cccf6f0334130a7010d62332c75b53e7d8cea715e52692b06e9cd41b05644be3"
77
65
 
78
- Gibberish::HMAC("key", "some data", :digest => :sha256)
79
- #=> 01add3f98ce4d49403d98362a046c6cca2c79d778426282c53e4f628f648c12b
80
-
81
- [Find out more](http://mdp.github.com/gibberish/Gibberish/HMAC.html)
66
+ [See the full docs](http://www.rubydoc.info/github/mdp/gibberish/Gibberish/HMAC)
82
67
 
83
68
  ## Digests
84
69
 
@@ -100,15 +85,29 @@ Other digests can be used
100
85
  Gibberish::SHA512("somedata")
101
86
  #=> a053441b6de662599ecb14c580d6637dcb856a66b2a40a952d39df772e47e98ea22f9e105b31463c5cf2472feae7649464fe89d99ceb6b0bc398a6926926f416
102
87
 
103
- [Find out more](http://mdp.github.com/gibberish/Gibberish/Digest.html)
88
+ [See the full docs](http://www.rubydoc.info/github/mdp/gibberish/Gibberish/Digest)
89
+
90
+ ## RSA
91
+
92
+ k = Gibberish::RSA.generate_keypair(2048)
93
+ cipher = Gibberish::RSA.new(k.public_key)
94
+ enc = cipher.encrypt("Some data")
95
+ # Defaults to Base64 output
96
+ #=> "JKm98wKyJljqmpx7kP8ZsdeXiShllEMcRHVnjUjc4ecyYK/doKAkVTLho1Gp\ng697qrljyClF0AcIH+XZmeF/TrqYUuCEUyhOD6OL1bs5dn8vFQefS5KdaC5Y\ndLADvh3mSfE/w/gs4vaf/OtbZNBeSl6ROCZasWTfRewp4n1RDmE=\n"
97
+ cipher = Gibberish::RSA.new(k.private_key)
98
+ dec = cipher.decrypt(enc)
99
+
100
+ [See the full docs](http://mdp.github.com/gibberish/Gibberish/RSA.html)
104
101
 
105
102
  ## Run the tests
106
103
 
107
104
  git clone https://github.com/mdp/gibberish.git
108
105
  cd gibberish
109
- bundle install
110
- rake test
106
+ make
107
+
108
+ ### Benchmarking AES with PBKDF2
111
109
 
112
- ## TODO
110
+ make benchmark
111
+ # Change the PBKDF2 iterations
112
+ ITER=10000 make benchmark
113
113
 
114
- - Cover OpenSSL exceptions with more reasonable and easier to understand exceptions.
data/gibberish.gemspec CHANGED
@@ -7,10 +7,12 @@ Gem::Specification.new do |s|
7
7
  s.version = Gibberish::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Mark Percival"]
10
- s.email = ["mark@markpercival.us"]
10
+ s.email = ["m@mdp.im"]
11
11
  s.homepage = "http://github.com/mdp/gibberish"
12
12
  s.summary = %q{An opinionated ruby encryption library}
13
- s.description = %q{Supports OpenSSL compatible AES, HMAC, and RSA encryption}
13
+ s.description = %q{Supports SJCL compatible AES encryption, HMAC, and Digests}
14
+ s.required_ruby_version = '>= 2.0.0'
15
+ s.license = "MIT"
14
16
 
15
17
  s.rubyforge_project = "gibberish"
16
18
 
data/lib/gibberish/aes.rb CHANGED
@@ -1,9 +1,16 @@
1
+ require 'json'
2
+ require 'delegate'
3
+ require 'securerandom'
4
+
1
5
  module Gibberish
2
- # Handles AES encryption and decryption in a way that is compatible
3
- # with OpenSSL.
6
+ # # Handles AES encryption and decryption with some sensible defaults
7
+ # - 256 bit AES encryption
8
+ # - GCM mode with Authentication
9
+ # - 100,000 iterations of PBKDF2_HMAC for key strengthening
4
10
  #
5
- # Defaults to 256-bit CBC encryption, ideally you should leave it
6
- # this way
11
+ # ## Compatibility with SJCL
12
+ # It outputs into a format that is compatible with SJCL and easy to
13
+ # consume in browsers/Node.js
7
14
  #
8
15
  # ## Basic Usage
9
16
  #
@@ -11,22 +18,193 @@ module Gibberish
11
18
  #
12
19
  # cipher = Gibberish::AES.new('p4ssw0rd')
13
20
  # cipher.encrypt("some secret text")
14
- # #=> "U2FsdGVkX1/D7z2azGmmQELbMNJV/n9T/9j2iBPy2AM=\n"
15
- # cipher.encrypt_file("secret.txt", "secret.txt.enc")
21
+ # #=> Outputs a JSON string containing all the necessary information
16
22
  #
17
23
  # ### Decrypting
18
24
  #
19
25
  # cipher = Gibberish::AES.new('p4ssw0rd')
20
- # cipher.decrypt(""U2FsdGVkX1/D7z2azGmmQELbMNJV/n9T/9j2iBPy2AM=\n"")
26
+ # cipher.decrypt('{"iv":"I4XKgNfMNkYhvzXc","v":1,"iter":1000,"ks":128,"ts":64,"mode":"gcm","adata":"123abc","cipher":"aes","salt":"PJsit8L16Ug=","ct":"5sEBsHXQqLXLOjxuVQK7fGZVdrMyRGDJ"}')
27
+ # #=> "some secret text"
28
+ #
29
+ # #### Including Authenticated data.
30
+ #
31
+ # GCM mode allows you to include "Authenticated Data" with the ciphertext, if you wish.
32
+ # For an overview of Authenticated Data, see this post: [http://crypto.stackexchange.com/a/15701](http://crypto.stackexchange.com/a/15701)
33
+ #
34
+ # Using AD is easy with Gibberish
35
+ #
36
+ # cipher = Gibberish::AES.new('p4ssw0rd')
37
+ # ciphertext = cipher.encrypt("Some secret data", "my authenticated data")
38
+ # plaintext = cipher.decrypt(ciphertext)
21
39
  # #=> "some secret text"
22
- # cipher.decrypt_file("secret.txt.enc", "secret.txt")
40
+ # plaintext.adata
41
+ # # => "my authenticated data"
42
+ #
43
+ # ## Interoperability with SJCL's GCM mode AES
44
+ #
45
+ # #### Decrypting
46
+ #
47
+ # ```javascript
48
+ # // In the browser
49
+ # var cleartext = sjcl.decrypt('key', '[output from Gibberish AES]');
50
+ # ```
51
+ #
52
+ # #### Encrypting
53
+ #
54
+ # Ruby OpenSSL cannot handle an IV longer than 12 bytes, therefore we need to tell SJCL to
55
+ # only use a 3 word IV value. See: https://github.com/bitwiseshiftleft/sjcl/issues/180
23
56
  #
24
- # ## OpenSSL Interop
57
+ # ```javascript
58
+ # // In the browser
59
+ # var ciphertext = sjcl.encrypt('key', 'plain text', {mode: 'gcm', iv: sjcl.random.randomWords(3, 0)});
60
+ # ```
25
61
  #
62
+ # ## Backward compatibility with older pre 2.0 Gibberish
63
+ #
64
+ # Gibberish was previously designed to be compatible with OpenSSL on the command line with CBC mode AES.
65
+ # This has been deprecated in favor of GCM mode. However, you may still
66
+ # decrypt and encrypt using legacy convenience methods below:
67
+ #
68
+ # (Note: OpenSSL "enc" uses a non-standard file format which lacks [key stretching](http://en.wikipedia.org/wiki/Key_stretching), this means less secure passwords are more susceptible to brute forcing.)
69
+ #
70
+ # ### AES-256-CBC mode
71
+ #
72
+ # cipher = Gibberish::AES::CBC.new('p4ssw0rd')
73
+ # cipher_text = cipher.encrypt("some secret text")
74
+ # # => U2FsdGVkX1/D7z2azGmmQELbMNJV/n9T/9j2iBPy2AM=
75
+ #
76
+ # cipher.decrypt(cipher_text)
77
+ #
78
+ # # From the command line
26
79
  # echo "U2FsdGVkX1/D7z2azGmmQELbMNJV/n9T/9j2iBPy2AM=\n" | openssl enc -d -aes-256-cbc -a -k p4ssw0rd
27
- # openssl aes-256-cbc -d -in secret.txt.enc -out secret.txt -k p4ssw0rd
28
80
  #
29
81
  class AES
82
+ # Returns the AES object
83
+ #
84
+ # @param [String] password
85
+ # @param [Hash] opts
86
+ # @option opts [Symbol] :mode ('gcm') the AES mode to use
87
+ # @option opts [Symbol] :ks (256) keystrength
88
+ # @option opts [Symbol] :iter (100_000) number of PBKDF2 iterations to run on the password
89
+ # @option opts [Symbol] :max_iter (100_000) maximum allow iterations, set to prevent DOS attack of someone setting a large 'iter' value in the ciphertext JSON
90
+ # @option opts [Symbol] :ts (64) length of the authentication data hash
91
+ def initialize(password, opts={})
92
+ @cipher = SJCL.new(password, opts)
93
+ end
94
+
95
+ # Returns the ciphertext in the form of a JSON string
96
+ #
97
+ # @param [String] data
98
+ # @param [String] authenticated_data (Won't be encrypted)
99
+ def encrypt(data, authenticated_data='')
100
+ @cipher.encrypt(data, authenticated_data)
101
+ end
102
+
103
+ # Returns a Plaintext object (essentially a String with an additional 'adata' attribute)
104
+ #
105
+ # @param [String] ciphertext
106
+ def decrypt(ciphertext)
107
+ @cipher.decrypt(ciphertext)
108
+ end
109
+
110
+ end
111
+
112
+ class AES::SJCL
113
+ class CipherOptionsError < ArgumentError; end
114
+ class DecryptionError < StandardError; end
115
+ class Plaintext < SimpleDelegator
116
+ attr_reader :adata
117
+ def initialize(str, adata)
118
+ @adata = adata;
119
+ super(str)
120
+ end
121
+ end
122
+
123
+ MAX_ITER = 100_000
124
+ ALLOWED_MODES = ['ccm', 'gcm']
125
+ ALLOWED_KS = [128, 192, 256]
126
+ ALLOWED_TS = [64, 96, 128]
127
+ DEFAULTS = {
128
+ v:1, iter:100_000, ks:256, ts:96,
129
+ mode:"gcm", adata:"", cipher:"aes", max_iter: MAX_ITER
130
+ }
131
+ def initialize(password, opts={})
132
+ @password = password
133
+ @opts = DEFAULTS.merge(opts)
134
+ check_cipher_options(@opts)
135
+ end
136
+
137
+ def encrypt(plaintext, adata='')
138
+ salt = SecureRandom.random_bytes(8)
139
+ iv = SecureRandom.random_bytes(12)
140
+ key = OpenSSL::PKCS5.pbkdf2_hmac(@password, salt, @opts[:iter], @opts[:ks]/8, 'SHA256')
141
+ cipherMode = "#{@opts[:cipher]}-#{@opts[:ks]}-#{@opts[:mode]}"
142
+ c = OpenSSL::Cipher.new(cipherMode)
143
+ c.encrypt
144
+ c.key = key
145
+ c.iv = iv
146
+ c.auth_data = adata
147
+ ct = c.update(plaintext) + c.final
148
+ tag = c.auth_tag(@opts[:ts]/8);
149
+ ct = ct + tag
150
+ out = {
151
+ v: @opts[:v], adata: adata, ks: @opts[:ks], ct: Base64.strict_encode64(ct).encode('utf-8'), ts: tag.length * 8,
152
+ mode: @opts[:mode], cipher: 'aes', iter: @opts[:iter], iv: Base64.strict_encode64(iv),
153
+ salt: Base64.strict_encode64(salt)
154
+ }
155
+ out.to_json
156
+ end
157
+
158
+ def decrypt(h)
159
+ begin
160
+ h = JSON.parse(h, {:symbolize_names => true})
161
+ rescue
162
+ raise "Unable to parse JSON of crypted text"
163
+ end
164
+ check_cipher_options(h)
165
+ key = OpenSSL::PKCS5.pbkdf2_hmac(@password, Base64.decode64(h[:salt]), h[:iter], h[:ks]/8, 'SHA256')
166
+ iv = Base64.decode64(h[:iv])
167
+ ct = Base64.decode64(h[:ct])
168
+ tag = ct[ct.length-h[:ts]/8,ct.length]
169
+ ct = ct[0,ct.length-h[:ts]/8]
170
+ cipherMode = "#{h[:cipher]}-#{h[:ks]}-#{h[:mode]}"
171
+ begin
172
+ c = OpenSSL::Cipher.new(cipherMode)
173
+ rescue RuntimeError => e
174
+ raise "OpenSSL error when initializing: #{e.message}"
175
+ end
176
+ c.decrypt
177
+ c.key = key
178
+ c.iv = iv
179
+ c.auth_tag = tag;
180
+ c.auth_data = h[:adata] || ""
181
+ begin
182
+ out = c.update(ct) + c.final();
183
+ rescue OpenSSL::Cipher::CipherError => e
184
+ raise DecryptionError.new();
185
+ end
186
+ return Plaintext.new(out.force_encoding('utf-8'), h[:adata])
187
+ end
188
+
189
+ # Assume the worst
190
+ def check_cipher_options(c_opts)
191
+ if @opts[:max_iter] < c_opts[:iter]
192
+ # Prevent DOS attacks from high PBKDF iterations
193
+ # You an increase this by passing in opts[:max_iter]
194
+ raise CipherOptionsError.new("Iteration count of #{c_opts[:iter]} exceeds the maximum of #{@opts[:max_iter]}")
195
+ elsif !ALLOWED_MODES.include?(c_opts[:mode])
196
+ raise CipherOptionsError.new("Mode '#{c_opts[:mode]}' not supported")
197
+ elsif !ALLOWED_KS.include?(c_opts[:ks])
198
+ raise CipherOptionsError.new("Keystrength of #{c_opts[:ks]} not supported")
199
+ elsif !ALLOWED_TS.include?(c_opts[:ts])
200
+ raise CipherOptionsError.new("Tag length of #{c_opts[:ts]} not supported")
201
+ elsif c_opts[:iv] && Base64.decode64(c_opts[:iv]).length > 12
202
+ raise CipherOptionsError.new("Initialization vector's greater than 12 bytes are not supported in Ruby.")
203
+ end
204
+ end
205
+ end
206
+
207
+ class AES::CBC
30
208
 
31
209
  BUFFER_SIZE = 4096
32
210
 
@@ -34,9 +34,8 @@ module Gibberish
34
34
  #
35
35
  # Shorcut alias: Gibberish::SHA1(data)
36
36
  #
37
- # @param [String] key
38
37
  # @param [#to_s] data
39
- # @param [Hash] options
38
+ # @param [Hash] opts
40
39
  # @option opts [Boolean] :binary (false) encode the data in binary, not Base64
41
40
  def self.sha1(data, opts={})
42
41
  data = data.to_s
@@ -51,9 +50,8 @@ module Gibberish
51
50
  #
52
51
  # Shorcut alias: Gibberish::SHA224(data)
53
52
  #
54
- # @param [String] key
55
53
  # @param [#to_s] data
56
- # @param [Hash] options
54
+ # @param [Hash] opts
57
55
  # @option opts [Boolean] :binary (false) encode the data in binary, not Base64
58
56
  def self.sha224(data, opts={})
59
57
  data = data.to_s
@@ -68,9 +66,8 @@ module Gibberish
68
66
  #
69
67
  # Shorcut alias: Gibberish::SHA256(data)
70
68
  #
71
- # @param [String] key
72
69
  # @param [#to_s] data
73
- # @param [Hash] options
70
+ # @param [Hash] opts
74
71
  # @option opts [Boolean] :binary (false) encode the data in binary, not Base64
75
72
  def self.sha256(data, opts={})
76
73
  data = data.to_s
@@ -85,9 +82,8 @@ module Gibberish
85
82
  #
86
83
  # Shorcut alias: Gibberish::SHA384(data)
87
84
  #
88
- # @param [String] key
89
85
  # @param [#to_s] data
90
- # @param [Hash] options
86
+ # @param [Hash] opts
91
87
  # @option opts [Boolean] :binary (false) encode the data in binary, not Base64
92
88
  def self.sha384(data, opts={})
93
89
  data = data.to_s
@@ -102,9 +98,8 @@ module Gibberish
102
98
  #
103
99
  # Shorcut alias: Gibberish::SHA512(data)
104
100
  #
105
- # @param [String] key
106
101
  # @param [#to_s] data
107
- # @param [Hash] options
102
+ # @param [Hash] opts
108
103
  # @option opts [Boolean] :binary (false) encode the data in binary, not Base64
109
104
  def self.sha512(data, opts={})
110
105
  data = data.to_s
@@ -119,9 +114,8 @@ module Gibberish
119
114
  #
120
115
  # Shorcut alias: Gibberish::MD5(data)
121
116
  #
122
- # @param [String] key
123
117
  # @param [#to_s] data
124
- # @param [Hash] options
118
+ # @param [Hash] opts
125
119
  # @option opts [Boolean] :binary (false) encode the data in binary, not Base64
126
120
  def self.md5(data, opts={})
127
121
  data = data.to_s
@@ -1,27 +1,28 @@
1
1
  module Gibberish
2
- # Easy to use HMAC, defaults to SHA1
2
+ # Easy to use HMAC
3
3
  #
4
4
  # ## Example
5
5
  #
6
- # Gibberish::HMAC('key', 'data') #=> 104152c5bfdca07bc633eebd46199f0255c9f49d
7
- # Gibberish::HMAC('key', 'data', :digest => :sha224)
8
- # #=> 19424d4210e50d7a4521b5f0d54b4b0cff3060deddccfd894fda5b3b
9
- # Gibberish::HMAC('key', 'data', :digest => :sha256)
6
+ # Gibberish::HMAC256('key', 'data')
10
7
  # #=> 5031fe3d989c6d1537a013fa6e739da23463fdaec3b70137d828e36ace221bd0
11
- # Gibberish::HMAC('key', 'data', :digest => :sha384)
8
+ # Gibberish::HMAC1('key', 'data') # SHA1
9
+ # #=> 104152c5bfdca07bc633eebd46199f0255c9f49d
10
+ # Gibberish::HMAC224('key', 'data') # SHA224
11
+ # #=> 19424d4210e50d7a4521b5f0d54b4b0cff3060deddccfd894fda5b3b
12
+ # Gibberish::HMAC384('key', 'data') # SHA384
12
13
  # #=> c5f97ad9fd1020c174d7dc02cf83c4c1bf15ee20ec555b690ad58e62da8a00ee
13
14
  # 44ccdb65cb8c80acfd127ebee568958a
14
- # Gibberish::HMAC('key', 'data', :digest => :sha512)
15
+ # Gibberish::HMAC512('key', 'data') # SHA512
15
16
  # #=> 3c5953a18f7303ec653ba170ae334fafa08e3846f2efe317b87efce82376253c
16
17
  # b52a8c31ddcde5a3a2eee183c2b34cb91f85e64ddbc325f7692b199473579c58
17
18
  #
18
19
  # ## OpenSSL CLI Interop
19
20
  #
20
- # echo -n "stuff" | openssl dgst -sha1 -hmac 'password'
21
+ # echo -n "stuff" | openssl dgst -sha256 -hmac 'password'
21
22
  #
22
23
  # is the same as
23
24
  #
24
- # Gibberish::HMAC('password', 'stuff')
25
+ # Gibberish::HMAC256('password', 'stuff')
25
26
  #
26
27
  class HMAC
27
28
  DIGEST = {
@@ -38,21 +39,38 @@ module Gibberish
38
39
  #
39
40
  # @param [String] key
40
41
  # @param [#to_s] data
41
- # @param [Hash] options
42
+ # @param [Symbol] digest
43
+ # @param [Hash] opts
42
44
  # @option opts [Symbol] :digest (:sha1) the digest to encode with
43
45
  # @option opts [Boolean] :binary (false) encode the data in binary, not Base64
44
- def self.digest(key, data, opts={})
46
+ def self.digest(key, data, digest, opts={})
45
47
  data = data.to_s
46
- digest_type = opts[:digest] || :sha1
47
48
  if opts[:binary]
48
- OpenSSL::HMAC.digest(DIGEST[digest_type], key, data)
49
+ OpenSSL::HMAC.digest(DIGEST[digest], key, data)
49
50
  else
50
- OpenSSL::HMAC.hexdigest(DIGEST[digest_type], key, data)
51
+ OpenSSL::HMAC.hexdigest(DIGEST[digest], key, data)
51
52
  end
52
53
  end
53
54
  end
54
55
 
55
- def self.HMAC(key, data, opts={})
56
- Gibberish::HMAC.digest(key, data, opts)
56
+ def self.HMAC1(key, data)
57
+ Gibberish::HMAC.digest(key, data, :sha1)
58
+ end
59
+
60
+ def self.HMAC224(key, data)
61
+ Gibberish::HMAC.digest(key, data, :sha224)
62
+ end
63
+
64
+ def self.HMAC256(key, data)
65
+ Gibberish::HMAC.digest(key, data, :sha256)
57
66
  end
67
+
68
+ def self.HMAC384(key, data)
69
+ Gibberish::HMAC.digest(key, data, :sha384)
70
+ end
71
+
72
+ def self.HMAC512(key, data)
73
+ Gibberish::HMAC.digest(key, data, :sha512)
74
+ end
75
+
58
76
  end
@@ -1,3 +1,3 @@
1
1
  module Gibberish
2
- VERSION = "1.4.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'benchmark'
4
+ require 'gibberish'
5
+
6
+ N = 50
7
+ ITERATIONS = ENV["ITER"].to_i || 100_000
8
+ PLAINTEXT = "Doner meatball turducken pig chuck turkey cow. Beef ribs picanha leberkas filet mignon chicken sirloin kevin jerky. Turkey venison beef ribs, turducken capicola biltong pork loin meatball cupim jowl pork chop pancetta. Filet mignon t-bone flank spare ribs chuck kielbasa capicola turkey shank doner shoulder meatloaf pancetta. Pork belly t-bone pork loin hamburger brisket alcatra. Ham tail brisket sausage hamburger, filet mignon landjaeger jerky corned beef biltong pork chop ball tip. Shoulder pork loin ham hock pastrami brisket chuck flank. Doner meatball turducken pig chuck turkey cow. Beef ribs picanha leberkas filet mignon chicken sirloin kevin jerky. Turkey venison beef ribs, turducken capicola biltong pork loin meatball cupim jowl pork chop pancetta. Filet mignon t-bone flank spare ribs chuck kielbasa capicola turkey shank doner shoulder meatloaf pancetta. Pork belly t-bone pork loin hamburger brisket alcatra. Ham tail brisket sausage hamburger, filet mignon landjaeger jerky corned beef biltong pork chop ball tip. Shoulder pork loin ham hock pastrami brisket chuck flank. Doner meatball turducken pig chuck turkey cow. Beef ribs picanha leberkas filet mignon chicken sirloin kevin jerky. Turkey venison beef ribs, turducken capicola biltong pork loin meatball cupim jowl pork chop pancetta. Filet mignon t-bone flank spare ribs chuck kielbasa capicola turkey shank doner shoulder meatloaf pancetta. Pork belly t-bone pork loin hamburger brisket alcatra. Ham tail brisket sausage hamburger, filet mignon landjaeger jerky corned beef biltong pork chop ball tip. Shoulder pork loin ham hock pastrami brisket chuck flank. Doner meatball turducken pig chuck turkey cow. Beef ribs picanha leberkas filet mignon chicken sirloin kevin jerky. Turkey venison beef ribs, turducken capicola biltong pork loin meatball cupim jowl pork chop pancetta. Filet mignon t-bone flank spare ribs chuck kielbasa capicola turkey shank doner shoulder meatloaf pancetta. Pork belly t-bone pork loin hamburger brisket alcatra. Ham tail brisket sausage hamburger, filet mignon landjaeger jerky corned beef biltong pork chop ball tip. Shoulder pork loin ham hock pastrami brisket chuck flank."
9
+
10
+ puts "Benchmarking AES GCM: Encrypting 512 bytes #{N} times, at #{ITERATIONS} iterations\n"
11
+ cipher = Gibberish::AES.new("s33krit", iter: ITERATIONS)
12
+ plaintext = PLAINTEXT.slice(0,512)
13
+ time = Benchmark.realtime {
14
+ N.times {
15
+ cipher.encrypt(plaintext)
16
+ }
17
+ }
18
+
19
+ puts "Avg time per encryption: #{'%.5f' % (time/N)}ms"
20
+
data/spec/aes_spec.rb CHANGED
@@ -1,10 +1,96 @@
1
+ # -*- encoding: utf-8 -*-
1
2
  require 'spec_helper'
2
3
  require 'tempfile'
3
4
 
4
- describe "the aes cipher" do
5
+ describe "the sjcl compatible implementation of aes" do
6
+
7
+ describe "decryption" do
8
+
9
+ before do
10
+ @cipher = Gibberish::AES.new("s33krit")
11
+ end
12
+ it "should decrypt gcm encoded text from SJCL" do
13
+ # With a 64bit authentication tag
14
+ json = '{"iv":"pO1RiSKSfmlLPMIS","v":1,"iter":1000,"ks":128,"ts":64,"mode":"gcm","adata":"","cipher":"aes","salt":"BC60XoGJqnY=","ct":"Jgm8bExXvpbEDxOxFDroBuFmczMlfF4G"}'
15
+ @cipher.decrypt(json).must_equal("This is a secret");
16
+ # With a 96bit authentication tag
17
+ json = '{"iv":"6ru5wmyPl2hfhMmb","v":1,"iter":1000,"ks":128,"ts":96,"mode":"gcm","adata":"","cipher":"aes","salt":"KhrgNREkjN4=","ct":"/0LMJz7pYDXSdFa+x3vL7uc46Nz7y5kV9DhEBQ=="}'
18
+ @cipher.decrypt(json).must_equal("This is a secret");
19
+ # With a 128bit authentication tag
20
+ json = '{"iv":"S79wFwpjbSMz1FSB","v":1,"iter":1000,"ks":128,"ts":128,"mode":"gcm","adata":"","cipher":"aes","salt":"KhrgNREkjN4=","ct":"j8pJmmilaJ6We2fEq/NvAxka4Z70F7IEK/m9/y3hHoo="}'
21
+ @cipher.decrypt(json).must_equal("This is a secret");
22
+ end
23
+ it "should include the adata with the plaintext" do
24
+ json = '{"iv":"w9Iugnn0HztMpm+y","v":1,"iter":1000,"ks":128,"ts":64,"mode":"gcm","adata":"123abc","cipher":"aes","salt":"Sw6NOinzVZ8=","ct":"djCIRln1PbuiLEkMb2AJZdT/"}'
25
+ plaintext = @cipher.decrypt(json)
26
+ plaintext.must_equal("plain text")
27
+ plaintext.adata.must_equal("123abc")
28
+ end
29
+ describe "exceptions" do
30
+ it "should check the iterations length before attempting to decrypt" do
31
+ json = '{"iv":"S79wFwpjbSMz1FSB","v":1,"iter":1000000,"ks":128,"ts":128,"mode":"gcm","adata":"","cipher":"aes","salt":"KhrgNREkjN4=","ct":"j8pJmmilaJ6We2fEq/NvAxka4Z70F7IEK/m9/y3hHoo="}'
32
+ e = assert_raises(Gibberish::AES::SJCL::CipherOptionsError) { @cipher.decrypt(json) }
33
+ assert_match(/Iteration count/, e.message)
34
+ end
35
+ it "should only allow authenticated modes" do
36
+ json = '{"iv":"6ru5wmyPl2hfhMmb","v":1,"iter":1000,"ks":128,"ts":96,"mode":"cbc","adata":"","cipher":"aes","salt":"KhrgNREkjN4=","ct":"/0LMJz7pYDXSdFa+x3vL7uc46Nz7y5kV9DhEBQ=="}'
37
+ e = assert_raises(Gibberish::AES::SJCL::CipherOptionsError) { @cipher.decrypt(json) }
38
+ assert_equal("Mode 'cbc' not supported", e.message)
39
+ end
40
+ it "should fail gracefully when attempting to decrypt an SJCL generated ciphertext with a >12 byte IV" do
41
+ json = '{"iv":"fGuapJg66vk0eNNyLHUk1w==","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"GRywsuW0M8E=","ct":"MUq4sLzEHtnUy2nTF8NEJQ=="}'
42
+ e = assert_raises(Gibberish::AES::SJCL::CipherOptionsError) { @cipher.decrypt(json) }
43
+ assert_match(/Initialization vector/, e.message)
44
+ end
45
+ it "should fail if the password is incorrect" do
46
+ json = '{"iv":"ovFbwlWH+tTHFORl","v":1,"iter":1000,"ks":128,"ts":64,"mode":"gcm","adata":"","cipher":"aes","salt":"ib5/ig2qqL8=","ct":"ruxTz/VWArVfte4qzUwF/z74"}'
47
+ assert_raises(Gibberish::AES::SJCL::DecryptionError) { @cipher.decrypt(json) }
48
+ end
49
+ it "should fail if the adata has be modified" do
50
+ json = '{"iv":"S79wFwpjbSMz1FSB","v":1,"iter":1000,"ks":128,"ts":128,"mode":"gcm","adata":"foo","cipher":"aes","salt":"KhrgNREkjN4=","ct":"j8pJmmilaJ6We2fEq/NvAxka4Z70F7IEK/m9/y3hHoo="}'
51
+ assert_raises(Gibberish::AES::SJCL::DecryptionError) {
52
+ @cipher.decrypt(json)
53
+ }
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "encryption" do
59
+
60
+ it "should encrypt text" do
61
+ @cipher = Gibberish::AES.new("s33krit")
62
+ plaintext = "This is some text, and some UTF-8 中华人民共和"
63
+ ciphertext = @cipher.encrypt(plaintext)
64
+ @cipher.decrypt(ciphertext).must_equal(plaintext);
65
+ end
66
+
67
+ it "should allow users to override the number of iterations" do
68
+ @cipher = Gibberish::AES.new("s33krit", {iter: 10_000})
69
+ plaintext = "This is some text"
70
+ ciphertext = @cipher.encrypt(plaintext)
71
+ JSON.parse(ciphertext)["iter"].must_equal(10_000)
72
+ @cipher.decrypt(ciphertext).must_equal(plaintext);
73
+ end
74
+
75
+ it "should set the correct JSON attributes in the ciphertext" do
76
+ @cipher = Gibberish::AES.new("s33krit")
77
+ plaintext = "This is some text"
78
+ ciphertext = JSON.parse(@cipher.encrypt(plaintext))
79
+ ciphertext["iter"].must_equal(100_000)
80
+ ciphertext["v"].must_equal(1)
81
+ ciphertext["ks"].must_equal(256)
82
+ ciphertext["ts"].must_equal(96)
83
+ ciphertext["mode"].must_equal("gcm")
84
+ ciphertext["cipher"].must_equal("aes")
85
+ end
86
+
87
+ end
88
+ end
89
+
90
+ describe "the openssl command line compatible aes cipher" do
5
91
 
6
92
  before do
7
- @cipher = Gibberish::AES.new("password")
93
+ @cipher = Gibberish::AES::CBC.new("password")
8
94
  end
9
95
 
10
96
  it "should encrypt text and be compatible with OpenSSL CLI" do
data/spec/hmac_spec.rb CHANGED
@@ -2,55 +2,56 @@ require 'spec_helper'
2
2
 
3
3
  describe "HMAC" do
4
4
 
5
- it "should hopefully work" do
6
- Gibberish::HMAC("password", "data").must_equal("08d13c72bed7ace5efadc09df109a78a5d713097")
5
+ it "should just work and default to sha256" do
6
+ Gibberish::HMAC256("password", "data").must_equal(
7
+ "cccf6f0334130a7010d62332c75b53e7d8cea715e52692b06e9cd41b05644be3")
7
8
  end
8
9
 
9
10
  it "should work with OpenSSL HMAC" do
10
- hmac = Gibberish::HMAC("password", "data\n")
11
- o_hmac = `echo "data" | openssl dgst -sha1 -hmac 'password' | sed 's/^.*= //'`
11
+ hmac = Gibberish::HMAC256("password", "data\n")
12
+ o_hmac = `echo "data" | openssl dgst -sha256 -hmac 'password' | sed 's/^.*= //'`
12
13
  hmac.must_equal(o_hmac.chomp)
13
14
  end
14
15
 
15
16
  it "should hopefully work for sha224" do
16
- Gibberish::HMAC("password", "data", :digest => :sha224).must_equal(
17
+ Gibberish::HMAC224("password", "data").must_equal(
17
18
  "f66aa39e91d003f7d3fc1205f77bd4947af51735a49e197fbd478728")
18
19
  end
19
20
 
20
21
  it "should work with OpenSSL HMAC for sha224" do
21
- hmac = Gibberish::HMAC("password", "data\n", :digest => :sha224)
22
+ hmac = Gibberish::HMAC224("password", "data\n")
22
23
  o_hmac = `echo "data" | openssl dgst -sha224 -hmac 'password' | sed 's/^.*= //'`
23
24
  hmac.must_equal(o_hmac.chomp)
24
25
  end
25
26
 
26
27
  it "should hopefully work for sha256" do
27
- Gibberish::HMAC("password", "data", :digest => :sha256).must_equal(
28
+ Gibberish::HMAC256("password", "data").must_equal(
28
29
  "cccf6f0334130a7010d62332c75b53e7d8cea715e52692b06e9cd41b05644be3")
29
30
  end
30
31
 
31
32
  it "should work with OpenSSL HMAC for sha256" do
32
- hmac = Gibberish::HMAC("password", "data\n", :digest => :sha256)
33
+ hmac = Gibberish::HMAC256("password", "data\n")
33
34
  o_hmac = `echo "data" | openssl dgst -sha256 -hmac 'password' | sed 's/^.*= //'`
34
35
  hmac.must_equal(o_hmac.chomp)
35
36
  end
36
37
 
37
- it "should hopefully work for sha384" do
38
- Gibberish::HMAC("password", "data", :digest => :sha384).must_equal(
38
+ it "should work for sha384" do
39
+ Gibberish::HMAC384("password", "data").must_equal(
39
40
  "2ed475691214fb85d086577d8d525c609b92520ebd793a74856b3ffd8d3477eaaf0b06ef9e06c8aa81cf29f95078aca6")
40
41
  end
41
42
 
42
43
  it "should work with OpenSSL HMAC for sha384" do
43
- hmac = Gibberish::HMAC("password", "data\n", :digest => :sha384)
44
+ hmac = Gibberish::HMAC384("password", "data\n")
44
45
  o_hmac = `echo "data" | openssl dgst -sha384 -hmac 'password' | sed 's/^.*= //'`
45
46
  hmac.must_equal(o_hmac.chomp)
46
47
  end
47
48
 
48
49
  it "should hopefully work for sha512" do
49
- Gibberish::HMAC("password", "data", :digest => :sha512).must_equal("abf85192282b501874f4803ea08672f2c9d6e656c57801023a0b1f4dd9492ba960efdb560a8618ec783327d6dc31577422651a4cf7eaf722d2caefbc04038c6e")
50
+ Gibberish::HMAC512("password", "data").must_equal("abf85192282b501874f4803ea08672f2c9d6e656c57801023a0b1f4dd9492ba960efdb560a8618ec783327d6dc31577422651a4cf7eaf722d2caefbc04038c6e")
50
51
  end
51
52
 
52
53
  it "should work with OpenSSL HMAC for sha512" do
53
- hmac = Gibberish::HMAC("password", "data\n", :digest => :sha512)
54
+ hmac = Gibberish::HMAC512("password", "data\n")
54
55
  o_hmac = `echo "data" | openssl dgst -sha512 -hmac 'password' | sed 's/^.*= //'`
55
56
  hmac.must_equal(o_hmac.chomp)
56
57
  end
data/spec/spec_helper.rb CHANGED
@@ -5,3 +5,4 @@ require 'minitest/autorun'
5
5
 
6
6
  require 'gibberish'
7
7
 
8
+ print "Ruby version #{RUBY_VERSION} - OpenSSL version: #{OpenSSL::OPENSSL_VERSION}\n"
metadata CHANGED
@@ -1,32 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gibberish
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Percival
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-02 00:00:00.000000000 Z
11
+ date: 2015-04-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Supports OpenSSL compatible AES, HMAC, and RSA encryption
13
+ description: Supports SJCL compatible AES encryption, HMAC, and Digests
14
14
  email:
15
- - mark@markpercival.us
15
+ - m@mdp.im
16
16
  executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
- - .gitignore
21
- - .gitmodules
22
- - .travis.yml
23
- - .yardoc/checksums
24
- - .yardoc/objects/root.dat
25
- - .yardoc/proxy_types
26
- - .yardopts
20
+ - ".gitignore"
21
+ - ".gitmodules"
22
+ - ".travis.yml"
23
+ - ".yardopts"
27
24
  - CHANGELOG.mdown
28
25
  - Gemfile
29
26
  - LICENSE
27
+ - Makefile
30
28
  - README.markdown
31
29
  - Rakefile
32
30
  - gibberish.gemspec
@@ -36,6 +34,7 @@ files:
36
34
  - lib/gibberish/hmac.rb
37
35
  - lib/gibberish/rsa.rb
38
36
  - lib/gibberish/version.rb
37
+ - spec/aes_benchmark.rb
39
38
  - spec/aes_spec.rb
40
39
  - spec/digest_spec.rb
41
40
  - spec/fixtures/secret.txt
@@ -48,7 +47,8 @@ files:
48
47
  - spec/rsa_spec.rb
49
48
  - spec/spec_helper.rb
50
49
  homepage: http://github.com/mdp/gibberish
51
- licenses: []
50
+ licenses:
51
+ - MIT
52
52
  metadata: {}
53
53
  post_install_message:
54
54
  rdoc_options: []
@@ -56,18 +56,19 @@ require_paths:
56
56
  - lib
57
57
  required_ruby_version: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 2.0.0
62
62
  required_rubygems_version: !ruby/object:Gem::Requirement
63
63
  requirements:
64
- - - '>='
64
+ - - ">="
65
65
  - !ruby/object:Gem::Version
66
66
  version: '0'
67
67
  requirements: []
68
68
  rubyforge_project: gibberish
69
- rubygems_version: 2.0.2
69
+ rubygems_version: 2.2.2
70
70
  signing_key:
71
71
  specification_version: 4
72
72
  summary: An opinionated ruby encryption library
73
73
  test_files: []
74
+ has_rdoc:
data/.yardoc/checksums DELETED
@@ -1,6 +0,0 @@
1
- lib/gibberish.rb 802b1397065b8f34b094cd5e797446a42c2c9b7e
2
- lib/gibberish/rsa.rb 84ee338b25ac16484c1b652b63c802a8085c9a82
3
- lib/gibberish/aes.rb c0f393617c375e47516948a7540eb2bd9f9a261c
4
- lib/gibberish/hmac.rb 51804f85036f2bea4885506ea92ec5b4d88e1486
5
- lib/gibberish/digest.rb 7ba5c16118b415ac12ef1aadbe11ca95e5d73902
6
- lib/gibberish/version.rb d2287491a538f55ab0e5d861eaf18da07ab46c89
Binary file
data/.yardoc/proxy_types DELETED
@@ -1,2 +0,0 @@
1
- {I" Object:EF:
2
- class