urlcrypt 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4b88fc478e4e9f1be07a35951eb871bfa2cacc5ca3d6478d95dff1ea24df138d
4
+ data.tar.gz: 6f01a73f86568c9baec085265539c0b889007ea570273b78609924fc1939a865
5
+ SHA512:
6
+ metadata.gz: b1a7d56dd3bcf4e27a396d3949e9e8cd546cc70a68bff62444ffee6d6e7a8bc1c8370ae94ba28fc24e4d37c01c979cd989d81370854dd7d10aff1489dac39ec7
7
+ data.tar.gz: a1322a2ebf8c4965c1f6945ba7bf9e61fde1566d5ea33fc05668897a0eb5c3133a83f5dc23ea5d649b7024b06dfec9b8dd0f0f79f04bd8b525919e81be7e636b
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # URLcrypt
2
2
 
3
- [![Build Status](https://travis-ci.org/madrobby/URLcrypt.png?branch=master)](https://travis-ci.org/madrobby/URLcrypt)
3
+ [![Build Status](https://travis-ci.org/cheerful/URLcrypt.png?branch=master)](https://travis-ci.org/cheerful/URLcrypt)
4
+ [![Coverage Status](https://coveralls.io/repos/cheerful/URLcrypt/badge.png?branch=master)](https://coveralls.io/r/cheerful/URLcrypt)
4
5
 
5
6
  Ever wanted to securely transmit (not too long) pieces of arbitrary binary data
6
7
  in a URL? **URLcrypt** makes it easy!
@@ -8,44 +9,53 @@ in a URL? **URLcrypt** makes it easy!
8
9
  This gem is based on the [base32](https://github.com/stesla/base32) gem from Samuel Tesla.
9
10
 
10
11
  URLcrypt uses **256-bit AES symmetric encryption**
11
- to securely encrypt data, and encodes and decodes
12
+ to securely encrypt data, and encodes and decodes
12
13
  **Base 32 strings that can be used directly in URLs**.
13
14
 
14
- This can be used to securely store user ids, download expiration dates and
15
- other arbitrary data like that when you access a web application from a place
15
+ This can be used to securely store user ids, download expiration dates and
16
+ other arbitrary data like that when you access a web application from a place
16
17
  that doesn't have other authentication or persistence mechanisms (like cookies):
17
-
18
+
18
19
  * Loading a generated image from your web app in an email
19
20
  * Links that come with an expiration date (à la S3)
20
21
  * Mini-apps that don't persist data on the server
21
22
 
22
- Works with Ruby 1.8, 1.9 and 2.0.
23
+ Works with Ruby 2.6+
23
24
 
24
- **Important**: As a general guideline, URL lengths shouldn't exceed about 2000
25
+ **Important**: As a general guideline, URL lengths shouldn't exceed about 2000
25
26
  characters in length, as URLs longer than that will not work in some browsers
26
27
  and with some (proxy) servers. This limits the amount of data you can store
27
28
  with URLcrypt.
28
29
 
29
30
  **WORD OF WARNING: THERE IS NO GUARANTEE WHATSOEVER THAT THIS GEM IS ACTUALLY SECURE AND WORKS. USE AT YOUR OWN RISK.**
30
31
 
32
+ URLcrypt is an extraction from [Noko Time Tracking](https://nokotime.com),
33
+ where it is used to generate URLs for dynamically generated images in emails.
34
+
31
35
  Patches are welcome; please include tests!
32
36
 
33
37
  ## Installation
34
38
 
35
- Add the `urlcrypt` gem to your Gemfile.
39
+ Add to your Gemfile:
40
+ ```ruby
41
+ gem 'urlcrypt', '~> 0.1.1', require: 'URLcrypt'
42
+ ```
43
+
44
+ Then, set `ENV['urlcrypt_key']` to the default encryption key you will be using. This should be at least a 256-bit AES key, see below. **To ensure your strings are encoded, URLcrypt uses `ENV.fetch` to check for the variable, so it _must_ be set.**
36
45
 
37
- ## Simple Example
46
+ ## Example
38
47
 
39
48
  ```ruby
40
- # encrypt and encode with 256-bit AES
41
- # one-time setup, set this to a securely random key with at least 256 bits, see below
42
- URLcrypt::key = '...'
43
-
44
- # now encrypt and decrypt!
45
- URLcrypt::encrypt('chunky bacon!') # => "sgmt40kbmnh1663nvwknxk5l0mZ6Av2ndhgw80rkypnp17xmmg5hy"
46
- URLcrypt::decrypt('sgmt40kbmnh1663nvwknxk5l0mZ6Av2ndhgw80rkypnp17xmmg5hy')
49
+ # encrypt and decrypt using the default key from ENV['urlcrypt_key']!
50
+ URLcrypt.encrypt('chunky bacon!') # => "sgmt40kbmnh1663nvwknxk5l0mZ6Av2ndhgw80rkypnp17xmmg5hy"
51
+ URLcrypt.decrypt('sgmt40kbmnh1663nvwknxk5l0mZ6Av2ndhgw80rkypnp17xmmg5hy')
47
52
  # => "chunky bacon!"
48
53
 
54
+ # If needed, you can specify a custom key per-call
55
+ URLcrypt.encrypt('chunky bacon!', key: '...') # => "....."
56
+ URLcrypt.decrypt('sgmt40kbmnh1663nvwknxk5l0mZ6Av2ndhgw80rkypnp17xmmg5hy', key: '...')
57
+ # => "chunky bacon!"
58
+
49
59
  # encoding without encryption (don't use for anything sensitive!), doesn't need key set
50
60
  URLcrypt.encode('chunky bacon!') # => "mnAhk6tlp2qg2yldn8xcc"
51
61
  URLcrypt.decode('mnAhk6tlp2qg2yldn8xcc') # => "chunky bacon!"
@@ -55,15 +65,15 @@ URLcrypt.decode('mnAhk6tlp2qg2yldn8xcc') # => "chunky bacon!"
55
65
 
56
66
  The easiest way to generate a secure key is to use `rake secret` in a Rails app:
57
67
 
58
- ```
59
- % rake secret
68
+ ```sh
69
+ $ rake secret
60
70
  ba7f56f8f9873b1653d7f032cc474938fd749ee8fbbf731a7c41d698826aca3cebfffa832be7e6bc16eaddc3826602f35d3fd6b185f261ee8b0f01d33adfbe64
61
71
  ```
62
72
 
63
73
  To use the key with URLcrypt, you'll need to convert that from a hex string into a real byte array:
64
74
 
65
- ```
66
- URLcrypt::key = ['longhexkeygoeshere'].pack('H*')
75
+ ```ruby
76
+ ENV['urlcrypt_key'] = ['longhexkeygoeshere'].pack('H*')
67
77
  ```
68
78
 
69
79
  ## Running the Test Suite
@@ -71,8 +81,8 @@ URLcrypt::key = ['longhexkeygoeshere'].pack('H*')
71
81
  If you want to run the automated tests for URLcrypt, issue this command from the
72
82
  distribution directory.
73
83
 
74
- ```
75
- % rake test:all
84
+ ```sh
85
+ $ rake test:all
76
86
  ```
77
87
 
78
88
  ## Why not Base 64, or an other radix/base library?
@@ -81,13 +91,13 @@ URLcrypt uses a modified Base 32 algorithm that doesn't use padding characters,
81
91
  and doesn't use vowels to avoid bad words in the generated string.
82
92
 
83
93
  The main reason why Base 32 is useful is that Ruby's built-in Base 64 support
84
- is, IMO, looking ugly in URLs and requires several characters that need to be
94
+ is, IMO, looking ugly in URLs and requires several characters that need to be
85
95
  URL-escaped.
86
96
 
87
- Unfortunately, some other gems out there that in theory could handle this
97
+ Unfortunately, some other gems out there that in theory could handle this
88
98
  (like the radix gem) fail with strings that start with a "\0" byte.
89
99
 
90
100
 
91
101
  ## References
92
102
 
93
- * Base 32: RFC 3548: http://www.faqs.org/rfcs/rfc3548.html
103
+ * Base 32: RFC 3548: http://www.faqs.org/rfcs/rfc3548.html
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2013 Thomas Fuchs
1
+ # Copyright (c) 2013-2022 Thomas Fuchs
2
2
  # Copyright (c) 2007-2011 Samuel Tesla
3
3
 
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,6 +24,7 @@ require 'rake/clean'
24
24
  require 'rake/testtask'
25
25
  require 'rubygems'
26
26
  require 'rubygems/package_task'
27
+ require 'bundler'
27
28
 
28
29
  task :default => ['test:all']
29
30
 
@@ -32,12 +33,11 @@ gemspec = Gem::Specification.new do |s|
32
33
  s.email = "thomas@slash7.com"
33
34
  s.extra_rdoc_files = ["README.md"]
34
35
  s.files = FileList["Rakefile", "{config,lib,test}/**/*"]
35
- s.has_rdoc = true
36
36
  s.name = 'urlcrypt'
37
37
  s.require_paths << 'lib'
38
38
  s.requirements << 'none'
39
39
  s.summary = "Securely encode and decode short pieces of arbitrary binary data in URLs."
40
- s.version = "0.1.0"
40
+ s.version = "0.2.0"
41
41
  end
42
42
 
43
43
  Gem::PackageTask.new(gemspec) do |pkg|
data/lib/URLcrypt.rb CHANGED
@@ -2,14 +2,10 @@ require 'openssl'
2
2
 
3
3
  module URLcrypt
4
4
  # avoid vowels to not generate four-letter words, etc.
5
- # this is important because those words can trigger spam
5
+ # this is important because those words can trigger spam
6
6
  # filters when URLs are used in emails
7
7
  TABLE = "1bcd2fgh3jklmn4pqrstAvwxyz567890".freeze
8
8
 
9
- def self.key=(key)
10
- @key = key
11
- end
12
-
13
9
  class Chunk
14
10
  def initialize(bytes)
15
11
  @bytes = bytes
@@ -31,7 +27,11 @@ module URLcrypt
31
27
  [(0..n-1).to_a.reverse.collect {|i| TABLE[(c >> i * 5) & 0x1f].chr},
32
28
  ("=" * (8-n))] # TODO: remove '=' padding generation
33
29
  end
34
-
30
+ end
31
+
32
+ def self.key=(key)
33
+ warn "`URLcrypt.key=` is deprecated. See the README on using environment variables with URLcrypt."
34
+ ENV['urlcrypt_key'] = [key].pack('H*')
35
35
  end
36
36
 
37
37
  def self.chunks(str, size)
@@ -52,27 +52,28 @@ module URLcrypt
52
52
  def self.decode(data)
53
53
  chunks(data, 8).collect(&:decode).flatten.join
54
54
  end
55
-
56
- def self.decrypt(data)
57
- parts = data.split('Z').map{|part| decode(part)}
58
- decrypter = cipher(:decrypt)
59
- decrypter.iv = parts[0]
60
- decrypter.update(parts[1]) + decrypter.final
55
+
56
+ def self.decrypt(data, key: ENV.fetch('urlcrypt_key'))
57
+ iv, encrypted = data.split('Z').map{|part| decode(part)}
58
+ fail DecryptError, "not a valid string to decrypt" unless iv && encrypted
59
+ decrypter = cipher(:decrypt, key: key)
60
+ decrypter.iv = iv
61
+ decrypter.update(encrypted) + decrypter.final
61
62
  end
62
-
63
- def self.encrypt(data)
64
- crypter = cipher(:encrypt)
63
+
64
+ def self.encrypt(data, key: ENV.fetch('urlcrypt_key'))
65
+ crypter = cipher(:encrypt, key: key)
65
66
  crypter.iv = iv = crypter.random_iv
66
67
  "#{encode(iv)}Z#{encode(crypter.update(data) + crypter.final)}"
67
68
  end
68
-
69
- private
70
-
71
- def self.cipher(mode)
69
+
70
+ private
71
+ def self.cipher(mode, key:)
72
72
  cipher = OpenSSL::Cipher.new('aes-256-cbc')
73
73
  cipher.send(mode)
74
- cipher.key = @key
74
+ cipher.key = key.byteslice(0,cipher.key_len)
75
75
  cipher
76
76
  end
77
77
 
78
- end
78
+ class DecryptError < ::ArgumentError; end
79
+ end
@@ -1,29 +1,7 @@
1
1
  # encoding: utf-8
2
- require 'test/unit'
3
- require 'URLcrypt'
4
-
5
- class TestURLcrypt < Test::Unit::TestCase
6
- def assert_bytes_equal(string1, string2)
7
- bytes1 = string1.bytes.to_a.join(':')
8
- bytes2 = string2.bytes.to_a.join(':')
9
- assert_equal(bytes1, bytes2)
10
- end
11
-
12
- def assert_decoding(encoded, plain)
13
- decoded = URLcrypt.decode(encoded)
14
- assert_bytes_equal(plain, decoded)
15
- end
16
-
17
- def assert_encoding(encoded, plain)
18
- actual = URLcrypt.encode(plain)
19
- assert_bytes_equal(encoded, actual)
20
- end
21
-
22
- def assert_encode_and_decode(encoded, plain)
23
- assert_encoding(encoded, plain)
24
- assert_decoding(encoded, plain)
25
- end
2
+ require 'test_helper'
26
3
 
4
+ class TestURLcrypt < TestClass
27
5
  def test_empty_string
28
6
  assert_encode_and_decode('', '')
29
7
  end
@@ -33,11 +11,11 @@ class TestURLcrypt < Test::Unit::TestCase
33
11
  '111gc86f4nxw5zj1b3qmhpb14n5h25l4m7111',
34
12
  "\0\0awesome \n ü string\0\0")
35
13
  end
36
-
14
+
37
15
  def test_invalid_encoding
38
16
  assert_decoding('ZZZZZ', '')
39
17
  end
40
-
18
+
41
19
  def test_arbitrary_byte_strings
42
20
  0.step(1500,17) do |n|
43
21
  original = (0..n).map{rand(256).chr}.join
@@ -45,15 +23,9 @@ class TestURLcrypt < Test::Unit::TestCase
45
23
  assert_decoding(encoded, original)
46
24
  end
47
25
  end
48
-
49
- def test_encryption
50
- # this key was generated via rake secret in a rails app, the pack() converts it into a byte array
51
- URLcrypt::key =
52
- ['d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d721968887a19bdb01af8f59eb5a90d256bd9903355c20b0b4b39bf4048b9b17b'].pack('H*')
53
-
54
- original = "hello world!"
55
- encrypted = URLcrypt::encrypt(original)
56
- assert_equal(URLcrypt::decrypt(encrypted), original)
57
- end
58
26
 
27
+ def test_key_deprecation
28
+ URLcrypt.key = 'aaaa'
29
+ assert_equal "\xAA\xAA", ENV.fetch('urlcrypt_key')
30
+ end
59
31
  end
@@ -0,0 +1,120 @@
1
+ # encoding: utf-8
2
+ require 'test_helper'
3
+
4
+ class URLcryptEncryptionTest < TestClass
5
+ def teardown
6
+ ENV["urlcrypt_key"] = nil
7
+ end
8
+
9
+ def test_requires_ENV_if_no_key_provided
10
+ error = assert_raises(KeyError) do
11
+ ::URLcrypt::decrypt("just some plaintext")
12
+ end
13
+ assert_equal error.message, "key not found: \"urlcrypt_key\""
14
+
15
+ error = assert_raises(KeyError) do
16
+ ::URLcrypt::encrypt("just some plaintext")
17
+ end
18
+ assert_equal error.message, "key not found: \"urlcrypt_key\""
19
+ end
20
+
21
+ def test_encryption_with_ENV_key
22
+ # pack() converts this secret into a byte array
23
+ secret = ['d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d'].pack('H*')
24
+ ENV['urlcrypt_key'] = secret
25
+
26
+ assert_equal OpenSSL::Cipher.new('aes-256-cbc').key_len, secret.bytesize
27
+
28
+ original = "hello world!"
29
+ encrypted = URLcrypt::encrypt(original)
30
+ assert_equal(URLcrypt::decrypt(encrypted), original)
31
+ end
32
+
33
+ def test_decrypt_error_with_ENV_key
34
+ secret = ['d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d'].pack('H*')
35
+ ENV['urlcrypt_key'] = secret
36
+ error = assert_raises(URLcrypt::DecryptError) do
37
+ ::URLcrypt::decrypt("just some plaintext")
38
+ end
39
+ assert_equal error.message, "not a valid string to decrypt"
40
+ end
41
+
42
+ def test_encryption_with_explicit_key
43
+ # pack() converts this secret into a byte array
44
+ secret = ['d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d'].pack('H*')
45
+
46
+ assert_equal OpenSSL::Cipher.new('aes-256-cbc').key_len, secret.bytesize
47
+
48
+ original = "hello world!"
49
+ encrypted = URLcrypt::encrypt(original, key: secret)
50
+ assert_equal(URLcrypt::decrypt(encrypted, key: secret), original)
51
+ end
52
+
53
+ def test_decrypt_error_with_explicit_key
54
+ secret = ['d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d'].pack('H*')
55
+ error = assert_raises(URLcrypt::DecryptError) do
56
+ ::URLcrypt::decrypt("just some plaintext", key: secret)
57
+ end
58
+ assert_equal error.message, "not a valid string to decrypt"
59
+ end
60
+
61
+ def test_threads_with_ENV_keys
62
+ # pack() converts this secret into a byte array
63
+ secret = ['d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d'].pack('H*')
64
+ ENV['urlcrypt_key'] = secret
65
+
66
+ assert_equal OpenSSL::Cipher.new('aes-256-cbc').key_len, secret.bytesize
67
+
68
+ parent_string = "hello world!"
69
+ parent_encrypted = URLcrypt::encrypt(parent_string)
70
+ assert_equal(URLcrypt::decrypt(parent_encrypted), parent_string)
71
+
72
+ threads = 100.times.map do |n|
73
+ Thread.new{
74
+ original = "Test String #{n}"
75
+ encrypted = URLcrypt::encrypt(original)
76
+ assert_equal(URLcrypt::decrypt(encrypted), original)
77
+
78
+ thread_encrypted = URLcrypt::encrypt(parent_string)
79
+
80
+ assert_equal(URLcrypt::decrypt(thread_encrypted), parent_string)
81
+ assert_equal(URLcrypt::decrypt(parent_encrypted), parent_string)
82
+ }
83
+ end
84
+
85
+ threads.each { |thr| thr.join }
86
+ end
87
+
88
+ def test_threads_with_explicit_per_thread_keys
89
+ threads = 100.times.map do |n|
90
+ Thread.new{
91
+ key = ["d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d-secret-key-#{n}"].pack('H*')
92
+ original = "Test String #{n}"
93
+ encrypted = URLcrypt::encrypt(original, key: key)
94
+ assert_equal(URLcrypt::decrypt(encrypted, key: key), original)
95
+ }
96
+ end
97
+
98
+ threads.each { |thr| thr.join }
99
+ end
100
+
101
+ def test_threads_with_explicit_per_thread_keys_overriding_ENV_variable
102
+ secret = ['d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d'].pack('H*')
103
+ ENV['urlcrypt_key'] = secret
104
+
105
+ threads = 100.times.map do |n|
106
+ Thread.new{
107
+ key = ["d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d-secret-key-#{n}"].pack('H*')
108
+
109
+ original = "Test String #{n}"
110
+ encrypted = URLcrypt::encrypt(original, key: key)
111
+ assert_equal(URLcrypt::decrypt(encrypted, key: key), original)
112
+
113
+ parent_encryption = URLcrypt::encrypt(original)
114
+ refute_equal parent_encryption, encrypted
115
+ }
116
+ end
117
+
118
+ threads.each { |thr| thr.join }
119
+ end
120
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+ class URLcryptRegressionTest < TestClass
3
+ def setup
4
+ # this key was generated via rake secret in a rails app, the pack() converts it into a byte array
5
+ @secret = ['d25883a27b9a639da85ea7e159b661218799c9efa63069fac13a6778c954fb6d721968887a19bdb01af8f59eb5a90d256bd9903355c20b0b4b39bf4048b9b17b'].pack('H*')
6
+ end
7
+
8
+ def test_encryption_and_decryption
9
+ original = '{"some":"json_data","token":"dfsfsdfsdf"}'
10
+ encrypted = URLcrypt.encrypt(original, key: @secret)
11
+
12
+ assert_equal(URLcrypt::decrypt(encrypted, key: @secret), original)
13
+ end
14
+
15
+ def test_encryption_with_too_long_key
16
+ assert OpenSSL::Cipher.new('aes-256-cbc').key_len < @secret.bytesize
17
+
18
+ original = "hello world!"
19
+ encrypted = URLcrypt::encrypt(original, key: @secret)
20
+ assert_equal(URLcrypt::decrypt(encrypted, key: @secret), original)
21
+ end
22
+
23
+ def test_encryption_and_decryption_with_too_long_key
24
+ assert OpenSSL::Cipher.new('aes-256-cbc').key_len < @secret.bytesize
25
+
26
+ original = '{"some":"json_data","token":"dfsfsdfsdf"}'
27
+ encrypted = URLcrypt.encrypt(original, key: @secret)
28
+
29
+ assert_equal(URLcrypt::decrypt(encrypted, key: @secret), original)
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ require 'bundler'
3
+ Bundler.require(:default, :test)
4
+
5
+ require 'simplecov'
6
+ SimpleCov.start
7
+
8
+ require "minitest/autorun"
9
+
10
+ class TestClass < Minitest::Test
11
+ require 'URLcrypt'
12
+
13
+ def assert_bytes_equal(string1, string2)
14
+ bytes1 = string1.bytes.to_a.join(':')
15
+ bytes2 = string2.bytes.to_a.join(':')
16
+ assert_equal(bytes1, bytes2)
17
+ end
18
+
19
+ def assert_decoding(encoded, plain)
20
+ decoded = URLcrypt.decode(encoded)
21
+ assert_bytes_equal(plain, decoded)
22
+ end
23
+
24
+ def assert_encoding(encoded, plain)
25
+ actual = URLcrypt.encode(plain)
26
+ assert_bytes_equal(encoded, actual)
27
+ end
28
+
29
+ def assert_encode_and_decode(encoded, plain)
30
+ assert_encoding(encoded, plain)
31
+ assert_decoding(encoded, plain)
32
+ end
33
+ end
metadata CHANGED
@@ -1,70 +1,52 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: urlcrypt
3
- version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Thomas Fuchs
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2013-03-18 00:00:00 Z
11
+ date: 2022-02-24 00:00:00.000000000 Z
19
12
  dependencies: []
20
-
21
13
  description:
22
14
  email: thomas@slash7.com
23
15
  executables: []
24
-
25
16
  extensions: []
26
-
27
- extra_rdoc_files:
17
+ extra_rdoc_files:
18
+ - README.md
19
+ files:
28
20
  - README.md
29
- files:
30
21
  - Rakefile
31
22
  - config/environment.rb
32
23
  - lib/URLcrypt.rb
33
24
  - test/URLcrypt_test.rb
34
- - README.md
25
+ - test/encryption_test.rb
26
+ - test/regression_test.rb
27
+ - test/test_helper.rb
35
28
  homepage:
36
29
  licenses: []
37
-
30
+ metadata: {}
38
31
  post_install_message:
39
32
  rdoc_options: []
40
-
41
- require_paths:
33
+ require_paths:
42
34
  - lib
43
35
  - lib
44
- required_ruby_version: !ruby/object:Gem::Requirement
45
- none: false
46
- requirements:
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
47
38
  - - ">="
48
- - !ruby/object:Gem::Version
49
- hash: 3
50
- segments:
51
- - 0
52
- version: "0"
53
- required_rubygems_version: !ruby/object:Gem::Requirement
54
- none: false
55
- requirements:
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
56
43
  - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
- version: "0"
62
- requirements:
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements:
63
47
  - none
64
- rubyforge_project:
65
- rubygems_version: 1.8.24
48
+ rubygems_version: 3.1.6
66
49
  signing_key:
67
- specification_version: 3
50
+ specification_version: 4
68
51
  summary: Securely encode and decode short pieces of arbitrary binary data in URLs.
69
52
  test_files: []
70
-