messagesodium 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c060a1d38eee8f3a480390a7150ea112f68fb0fa
4
- data.tar.gz: a5c72b3f85ed0b3a43f33f5ef03aeaa402dc3478
3
+ metadata.gz: 3bbe8437f3f0156fccf90bb3defdf1b565057196
4
+ data.tar.gz: 01b0de5ed925df8cc9c501b83b07899acfa83b9b
5
5
  SHA512:
6
- metadata.gz: 8df7f3adaae862c22ebd497eeed5ab8af18e3bbc8d716fe294d6d88bd4f5c46e86a568754e0b9a53aeb9af1cbed0c4e139ff8ade3467cd6defe87bc221e6b4c9
7
- data.tar.gz: ee86b1d422e378c337b0f5792867fb0a19c5b06325bef6668dacb359466ac3553dbaab975836bfa3eecb344e3a420121e1f4c679b0f70e80b8d77b226fbdf20e
6
+ metadata.gz: 7d901c443944865798e2485a7d78da76abdd6110d2d432f1255887c5352bd5470691290cfb74b3c297e6b4f98d71d3348f2cb7d6c3c22ee3c71e21bb6b271a15
7
+ data.tar.gz: 75cb3cafda0ebbd2792c8f7a049f3fa0854dcfe8e10e88ccb0b7a2968c654f5bfb0af74acb80d7ce04e83d1657e494da41bc4b352f8fe231c2b539fe4001ff21
data/.rubocop.yml ADDED
@@ -0,0 +1,14 @@
1
+ Style/StringLiterals:
2
+ Enabled: false
3
+
4
+ Metrics/AbcSize:
5
+ Max: 30
6
+
7
+ Metrics/LineLength:
8
+ Max: 90
9
+
10
+ Style/PercentLiteralDelimiters:
11
+ Enabled: false
12
+
13
+ Style/UnneededPercentQ:
14
+ Enabled: false
data/README.md CHANGED
@@ -3,3 +3,72 @@
3
3
  Project status: Turbo Pre-alpha
4
4
 
5
5
  Patches Cookiestore to use libsodium for encryption and verification.
6
+
7
+ # Cookistore
8
+
9
+ Rails [Cookiestore](https://www.justinweiss.com/articles/how-rails-sessions-work/) is a heavily underrated feature. It bought commonsense to session management at a time when [saving every user session in its own tmpfile on a server](http://php.net/manual/en/function.session-start.php) was slow and unreasonable to scale, and XXX.
10
+
11
+ This gem brings an alternative backend to CookieStore.
12
+
13
+ # Use
14
+
15
+ Just insert this gem into your Gemfile like any other:
16
+
17
+ gem 'messagesodium'
18
+
19
+ And run your usual bundle installation. Any existing sessions will be invalidated, much like if you changed your secret key.
20
+ You can test it is active by looking at any session cookie. The absence of the "--" delimeter will confirm you are using this gem.
21
+
22
+ # Demonstration
23
+
24
+ [This gist](https://gist.github.com/technion/5cb2c6fbc570f6c1bc66e30bfb072cdf) shows a few interesting benchmarks, which we can refer to when describing what this gem offers.
25
+
26
+ ```
27
+
28
+ Cookiestore data is: SWFQbTg0dCtheE45TXU0dWRtT25ndjJVSEdWTE8vei9LMVpZYWVjaWZjaFppdUk5aklVRWZEUy9TOUJuMFpYd2dDMndVZkt0eTR5Sm04Y1FjQzk0M00wRnhTRERHdDhnT3c1dTBvTnRad009LS16WlFaeE82dy84VzA4NThYQzk5bTVBPT0=--efcb8809421d2dc1665c9d9afa9638c1c2a763eb
29
+ which is 222 in length
30
+ Sodium data is: SGwQn0DD+pOvTPo68nvNYQLRFMt+Mf7rFU6BkiKhA0qHGT8BHVuqXRqEOYy+xcOoMCCRh99eeb/sVWlPzA4/FavTyg4U0PUAns0bx/Q9j4gcoD6K/h0z8yZvW0425g==
31
+ which is 128 in length
32
+ user system total real
33
+ to_json 2.470000 0.000000 2.470000 ( 2.514048)
34
+ JSON.dump 0.520000 0.000000 0.520000 ( 0.534084)
35
+ cookiestore encrypt and sign 1.810000 0.030000 1.840000 ( 1.915375)
36
+ cookiestore decrypt and verify 2.730000 0.000000 2.730000 ( 2.824819)
37
+ libsodium encrypt and sign 1.580000 0.060000 1.640000 ( 1.738750)
38
+ libsodium decrypt 1.010000 0.000000 1.010000 ( 1.035354)
39
+
40
+ ```
41
+
42
+ ## Smaller cookies
43
+
44
+ A welcome consequence is that of smaller cookies. This isn't strictly the result of changed encryption algorithms, but CookieStore's message packing is somewhat ineffecient. It is effectively:
45
+
46
+ Base64(Base64(iv) || "--" || Base64(message)) || "--" HMAC
47
+
48
+ If you can understand the reasoning for double Base64 encoding you're smarter than I am, but it adds to the four delimiting bytes. The authenticator on Poly1305 is also four bytes shorter than SHA1. You can see the end result in the above benchmark - 222 bytes vs 128 for our sample.
49
+
50
+ Smaller cookies are a good thing. It's less data on the wire for every single page hit, and it's more room to move around the 4Kb limit.
51
+
52
+ ## More performant
53
+
54
+ The above benchmark shows our approach as much more performant. Some of that is just crypto, which can be hardware dependant.
55
+
56
+ But some of this is down to the message packing. Dipping into Base64 functions three separate times to open one cookie is ineffecient. When the IV is known to be of BLOCKSIZE length, choosing to cut it by using split() and a delimiter is the long way around. In the end, performance is great.
57
+
58
+ ## A modern security approach
59
+
60
+ Let's be clear about the fact that I have no known issue with the current CookieStore implementation. However, it's worth having a read of the view of [Google's Adam Langley](https://www.imperialviolet.org/2013/10/07/chacha20.html) when describing "a strong motivation to replace it" when describing CBC mode.
61
+
62
+ Indeed, the are several comments in the original Rails source code to the effect of "this dance is done in the hope we don't introduce a vulnerability".
63
+
64
+ What you'll find in this gem is a much smaller, more easily audited codebase without any hoops to jump through.
65
+
66
+ # Approach
67
+
68
+ This gem is designed largely as a drop-in replacement for MessageEncryptor, which in turn is used by CookieStore. In a defualt environment, Rails astracts away everything I say below.
69
+
70
+ MessageEncryptor takes a "secret", and a "signing secret", using them as two different secrets. Libsodium only needs a 256-bit secret.
71
+
72
+ MessageEncryptor offers the option to provide an OpenSSL cipher. Obviously none of these apply to our gem. Finally, MessageEncryptor offers its choice of serializers. It defaults to Marshal, which was always a bad move, so Rails started to implicitly set JSON as the serializer in version 4.1. There's no reason in my view to let people have a footgun like this, so all this gem supports is JSON.
73
+
74
+ In order to make this "drop in", all the above parameters can still be provided, they are just ignored.
data/Rakefile CHANGED
@@ -4,7 +4,8 @@ require "rake/testtask"
4
4
  Rake::TestTask.new(:test) do |t|
5
5
  t.libs << "test"
6
6
  t.libs << "lib"
7
+ t.warning = true
7
8
  t.test_files = FileList['test/**/*_test.rb']
8
9
  end
9
10
 
10
- task :default => :test
11
+ task default: :test
data/lib/messagesodium.rb CHANGED
@@ -10,37 +10,37 @@ module ActiveSupport
10
10
  #
11
11
  # The cipher text and initialization vector are base64 encoded and returned
12
12
  # to you.
13
- #
14
13
  class MessageEncryptor
15
14
  class InvalidMessage < StandardError; end
16
15
 
17
- def initialize(secret, *signature_key_or_options)
18
- # The options and signature fields are unused.
19
- # However we need to retain them as they exist in the original function
16
+ # Uses "secret" as a libsodium Simplebox initialiser
17
+ # Secret must be 32 bytes (256-bit) long
18
+ # The options and signature fields are unused as lidsodium does not require
19
+ # a second key for an HMAC.
20
+ # However we need to retain them as they exist in the original function
21
+ def initialize(secret, *_signature_key_or_options)
20
22
  @box = RbNaCl::SimpleBox.from_secret_key(secret)
21
23
  end
22
24
 
23
- # Encrypt and sign a message. We need to sign the message in order to avoid
24
- # padding attacks. Reference: http://www.limited-entropy.com/padding-oracle-attacks.
25
+ # Encrypt and authenticate using libsodium XSalsa20/Poly1305
26
+ # Serialise with JSON.dump
27
+ # Returns base64(random nonce + cipher + auth tag)
25
28
  def encrypt_and_sign(value)
26
- Base64.strict_encode64(@box.encrypt(value.to_json))
29
+ Base64.strict_encode64(@box.encrypt(::JSON.dump(value)))
27
30
  end
28
31
 
29
- # Decrypt and verify a message. We need to verify the message in order to
30
- # avoid padding attacks. Reference: http://www.limited-entropy.com/padding-oracle-attacks.
32
+ # Decrypt the message, and check the auth tag in the process.
31
33
  def decrypt_and_verify(value)
32
- begin
33
- JSON.parse(@box.decrypt(Base64.decode64(value)), symbolize_names: true)
34
- rescue RbNaCl::CryptoError
35
- raise InvalidMessage
36
- end
34
+ ::JSON.parse(@box.decrypt(Base64.decode64(value)), symbolize_names: true)
35
+ rescue RbNaCl::CryptoError
36
+ raise InvalidMessage
37
37
  end
38
38
 
39
- # Given a cipher, returns the key length of the cipher to help generate the key of desired size
40
- def self.key_len(cipher)
39
+ # Given a cipher, returns the key length of the cipher to help generate
40
+ # the key of desired size
41
+ def self.key_len(_cipher = nil)
41
42
  # Ignore the cipher - libsodium knows what it's doing.
42
43
  RbNaCl::SecretBox.key_bytes
43
44
  end
44
45
  end
45
-
46
46
  end
@@ -1,3 +1,3 @@
1
1
  module Messagesodium
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0".freeze
3
3
  end
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Technion"]
10
10
  spec.email = ["technion@lolware.net"]
11
11
 
12
- spec.summary = %q{Patches Cookiestore to use Libsodium for encryption and verification.}
13
- spec.description = %q{Write a longer description or delete this line.}
12
+ spec.summary = %q{Patches MessageEncryptor/Cookiestore to use Libsodium .}
13
+ spec.description = %q{Introduces modern crypto, higher performance, smaller cookies to your sessions.}
14
14
  spec.homepage = "https://github.com/technion/messagesodium"
15
15
  spec.license = "MIT"
16
16
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: messagesodium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Technion
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-03 00:00:00.000000000 Z
11
+ date: 2017-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbnacl-libsodium
@@ -66,7 +66,8 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '5.0'
69
- description: Write a longer description or delete this line.
69
+ description: Introduces modern crypto, higher performance, smaller cookies to your
70
+ sessions.
70
71
  email:
71
72
  - technion@lolware.net
72
73
  executables: []
@@ -74,6 +75,7 @@ extensions: []
74
75
  extra_rdoc_files: []
75
76
  files:
76
77
  - ".gitignore"
78
+ - ".rubocop.yml"
77
79
  - ".travis.yml"
78
80
  - Gemfile
79
81
  - LICENSE.txt
@@ -107,5 +109,5 @@ rubyforge_project:
107
109
  rubygems_version: 2.6.11
108
110
  signing_key:
109
111
  specification_version: 4
110
- summary: Patches Cookiestore to use Libsodium for encryption and verification.
112
+ summary: Patches MessageEncryptor/Cookiestore to use Libsodium .
111
113
  test_files: []