slosilo 1.1.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: 19532fb817cc0d993257331452fd6fc36be49da8
4
- data.tar.gz: 63c9b867b4e125aff0e5680e21a9a31605629716
3
+ metadata.gz: 761d6e24aaa95427bbc3d7449bc980b29b602bca
4
+ data.tar.gz: 79950d2ab62c71a6f9ebdb1f68afdfd13c53894e
5
5
  SHA512:
6
- metadata.gz: 799000b32ea19b4b5ca3fb63901007e16c659af8ea383f3d469ed4a91a1c23b10529eeffda3167b73e0bf67043258622c997b68fefd110cf5fb96cedc8b3769c
7
- data.tar.gz: c017465fd76fd4aa9812924ead3c3342d66d3f87f222cd94c0f08c0eadd2dd66c7088e3bc5333ae6d4a83f165c2329456cc38158b2de5d17e76dd1fe0d098449
6
+ metadata.gz: de1ab282bd0067317a21e2d40dbb0668c737e487bc2e29e25120f460191d2c8a550b25ec98719a4d99d72176a73f0b47007703733ad5a0e77077a13c1fc54d6d
7
+ data.tar.gz: e7444706c7f1af27f3a7eebf350252b37a033ca4b225a5d8ea6d24afbf49f40d42e6613187f8f0fe2322c9bf73dc1b54d5e36796ba7ef10aa8c95ff54f5aa8b3
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Slosilo is providing a ruby interface to some cryptographic primitives:
4
4
  - symmetric encryption,
5
- - a mixin for easy encryption of object attributes (WARNING: unauthenticated, see below),
5
+ - a mixin for easy encryption of object attributes,
6
6
  - asymmetric encryption and signing,
7
7
  - a keystore in a postgres sequel db -- it allows easy storage and retrieval of keys,
8
8
  - a keystore in files.
@@ -17,6 +17,20 @@ And then execute:
17
17
 
18
18
  $ bundle
19
19
 
20
+ ## Compatibility
21
+
22
+ Version 2.0 introduced new symmetric encryption scheme using AES-256-GCM
23
+ for authenticated encryption. It allows you to provide AAD on all symmetric
24
+ encryption primitives. It's also **NOT COMPATIBLE** with CBC used in version <2.
25
+
26
+ This means you'll have to migrate all your existing data. There's no easy way to
27
+ do this currently provided; it's recommended to create a database migration and
28
+ put relevant code fragments in it directly. (This will also have the benefit of making
29
+ the migration self-contained.)
30
+
31
+ Since symmetric encryption is used in processing asymetrically encrypted messages,
32
+ this incompatibility extends to those too.
33
+
20
34
  ## Usage
21
35
 
22
36
  ### Symmetric encryption
@@ -24,12 +38,14 @@ And then execute:
24
38
  ```ruby
25
39
  sym = Slosilo::Symmetric.new
26
40
  key = sym.random_key
27
- ciphertext = sym.encrypt "secret message", key: key
41
+ # additional authenticated data
42
+ message_id = "message 001"
43
+ ciphertext = sym.encrypt "secret message", key: key, aad: message_id
28
44
  ```
29
45
 
30
46
  ```ruby
31
47
  sym = Slosilo::Symmetric.new
32
- message = sym.decrypt ciphertext, key: key
48
+ message = sym.decrypt ciphertext, key: key, aad: message_id
33
49
  ```
34
50
 
35
51
  ### Encryption mixin
@@ -39,11 +55,15 @@ require 'slosilo'
39
55
 
40
56
  class Foo
41
57
  attr_accessor :foo
42
- attr_encrypted :foo
58
+ attr_encrypted :foo, aad: :id
43
59
 
44
60
  def raw_foo
45
61
  @foo
46
62
  end
63
+
64
+ def id
65
+ "unique record id"
66
+ end
47
67
  end
48
68
 
49
69
  Slosilo::encryption_key = Slosilo::Symmetric.new.random_key
@@ -56,13 +76,6 @@ obj.foo # => "bar"
56
76
 
57
77
  You can safely use it in ie. ActiveRecord::Base or Sequel::Model subclasses.
58
78
 
59
- #### Warning
60
-
61
- The encrypted data is not authenticated; it's intended to prevent
62
- opportunistic access to secrets by a third party which gets hold of a database
63
- dump. *IT DOES NOT prevent tampering.* If your threat model includes an attacker
64
- which can modify the database, `attr_encrypted` by itself IS NOT SECURE.
65
-
66
79
  ### Asymmetric encryption and signing
67
80
 
68
81
  ```ruby
@@ -14,7 +14,7 @@ module Slosilo
14
14
  def create_model
15
15
  model = Sequel::Model(:slosilo_keystore)
16
16
  model.unrestrict_primary_key
17
- model.attr_encrypted :key if secure?
17
+ model.attr_encrypted(:key, aad: :id) if secure?
18
18
  model
19
19
  end
20
20
 
@@ -5,21 +5,44 @@ module Slosilo
5
5
  # so we encrypt sensitive attributes before storing them
6
6
  module EncryptedAttributes
7
7
  module ClassMethods
8
+
9
+ # @param options [Hash]
10
+ # @option :aad [#to_proc, #to_s] Provide additional authenticated data for
11
+ # encryption. This should be something unique to the instance having
12
+ # this attribute, such as a primary key; this will ensure that an attacker can't swap
13
+ # values around -- trying to decrypt value with a different auth data will fail.
14
+ # This means you have to be able to recover it in order to decrypt attributes.
15
+ # The following values are accepted:
16
+ #
17
+ # * Something proc-ish: will be called with self each time auth data is needed.
18
+ # * Something stringish: will be to_s-d and used for all instances as auth data.
19
+ # Note that this will only prevent swapping in data using another string.
20
+ #
21
+ # The recommended way to use this option is to pass a proc-ish that identifies the record.
22
+ # Note the proc-ish can be a simple method name; for example in case of a Sequel::Model:
23
+ # attr_encrypted :secret, aad: :pk
8
24
  def attr_encrypted *a
25
+ options = a.last.is_a?(Hash) ? a.pop : {}
26
+ aad = options[:aad]
27
+ # note nil.to_s is "", which is exactly the right thing
28
+ auth_data = aad.respond_to?(:to_proc) ? aad.to_proc : proc{ |_| aad.to_s }
29
+ raise ":aad proc must take one argument" unless auth_data.arity.abs == 1 # take abs to allow *args arity, -1
30
+
9
31
  # push a module onto the inheritance hierarchy
10
32
  # this allows calling super in classes
11
33
  include(accessors = Module.new)
12
34
  accessors.module_eval do
13
35
  a.each do |attr|
14
36
  define_method "#{attr}=" do |value|
15
- super(EncryptedAttributes.encrypt value)
37
+ super(EncryptedAttributes.encrypt(value, aad: auth_data[self]))
16
38
  end
17
39
  define_method attr do
18
- EncryptedAttributes.decrypt(super())
40
+ EncryptedAttributes.decrypt(super(), aad: auth_data[self])
19
41
  end
20
42
  end
21
43
  end
22
44
  end
45
+
23
46
  end
24
47
 
25
48
  def self.included base
@@ -27,14 +50,14 @@ module Slosilo
27
50
  end
28
51
 
29
52
  class << self
30
- def encrypt value
53
+ def encrypt value, opts={}
31
54
  return nil unless value
32
- cipher.encrypt value, key: key
55
+ cipher.encrypt value, key: key, aad: opts[:aad]
33
56
  end
34
57
 
35
- def decrypt ctxt
58
+ def decrypt ctxt, opts={}
36
59
  return nil unless ctxt
37
- cipher.decrypt ctxt, key: key
60
+ cipher.decrypt ctxt, key: key, aad: opts[:aad]
38
61
  end
39
62
 
40
63
  def key
@@ -1,25 +1,40 @@
1
1
  module Slosilo
2
2
  class Symmetric
3
+ VERSION_MAGIC = 'G'
4
+ TAG_LENGTH = 16
5
+
3
6
  def initialize
4
- @cipher = OpenSSL::Cipher.new 'AES-256-CBC'
7
+ @cipher = OpenSSL::Cipher.new 'aes-256-gcm' # NB: has to be lower case for whatever reason.
5
8
  end
6
-
9
+
10
+ # This lets us do a final sanity check in migrations from older encryption versions
11
+ def cipher_name
12
+ @cipher.name
13
+ end
14
+
7
15
  def encrypt plaintext, opts = {}
8
16
  @cipher.reset
9
17
  @cipher.encrypt
10
- @cipher.key = opts[:key]
18
+ @cipher.key = (opts[:key] or raise("missing :key option"))
11
19
  @cipher.iv = iv = random_iv
12
- ctxt = @cipher.update(plaintext)
13
- iv + ctxt + @cipher.final
20
+ @cipher.auth_data = opts[:aad] || "" # Nothing good happens if you set this to nil, or don't set it at all
21
+ ctext = @cipher.update(plaintext) + @cipher.final
22
+ tag = @cipher.auth_tag(TAG_LENGTH)
23
+ "#{VERSION_MAGIC}#{tag}#{iv}#{ctext}"
14
24
  end
15
-
25
+
16
26
  def decrypt ciphertext, opts = {}
27
+ version, tag, iv, ctext = unpack ciphertext
28
+
29
+ raise "Invalid version magic: expected #{VERSION_MAGIC} but was #{version}" unless version == VERSION_MAGIC
30
+
17
31
  @cipher.reset
18
32
  @cipher.decrypt
19
33
  @cipher.key = opts[:key]
20
- @cipher.iv, ctxt = ciphertext.unpack("a#{@cipher.iv_len}a*")
21
- ptxt = @cipher.update(ctxt)
22
- ptxt + @cipher.final
34
+ @cipher.iv = iv
35
+ @cipher.auth_tag = tag
36
+ @cipher.auth_data = opts[:aad] || ""
37
+ @cipher.update(ctext) + @cipher.final
23
38
  end
24
39
 
25
40
  def random_iv
@@ -29,5 +44,11 @@ module Slosilo
29
44
  def random_key
30
45
  @cipher.random_key
31
46
  end
47
+
48
+ private
49
+ # return tag, iv, ctext
50
+ def unpack msg
51
+ msg.unpack "aa#{TAG_LENGTH}a#{@cipher.iv_len}a*"
52
+ end
32
53
  end
33
54
  end
@@ -1,3 +1,3 @@
1
1
  module Slosilo
2
- VERSION = "1.1.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+ require 'slosilo/attr_encrypted'
3
+
4
+ describe Slosilo::EncryptedAttributes do
5
+ before(:all) do
6
+ Slosilo::encryption_key = OpenSSL::Cipher.new("aes-256-gcm").random_key
7
+ end
8
+
9
+ let(:aad) { proc{ |_| "hithere" } }
10
+
11
+ let(:base){
12
+ Class.new do
13
+ attr_accessor :normal_ivar,:with_aad
14
+ def stupid_ivar
15
+ side_effect!
16
+ @_explicit
17
+ end
18
+ def stupid_ivar= e
19
+ side_effect!
20
+ @_explicit = e
21
+ end
22
+ def side_effect!
23
+
24
+ end
25
+ end
26
+ }
27
+
28
+ let(:sub){
29
+ Class.new(base) do
30
+ attr_encrypted :normal_ivar, :stupid_ivar
31
+ end
32
+ }
33
+
34
+ subject{ sub.new }
35
+
36
+ context "when setting a normal ivar" do
37
+ let(:value){ "some value" }
38
+ it "stores an encrypted value in the ivar" do
39
+ subject.normal_ivar = value
40
+ expect(subject.instance_variable_get(:"@normal_ivar")).to_not eq(value)
41
+ end
42
+
43
+ it "recovers the value set" do
44
+ subject.normal_ivar = value
45
+ expect(subject.normal_ivar).to eq(value)
46
+ end
47
+ end
48
+
49
+ context "when setting an attribute with an implementation" do
50
+ it "calls the base class method" do
51
+ expect(subject).to receive_messages(:side_effect! => nil)
52
+ subject.stupid_ivar = "hi"
53
+ expect(subject.stupid_ivar).to eq("hi")
54
+ end
55
+ end
56
+
57
+ context "when given an :aad option" do
58
+
59
+ let(:cipher){ Slosilo::EncryptedAttributes.cipher }
60
+ let(:key){ Slosilo::EncryptedAttributes.key}
61
+ context "that is a string" do
62
+ let(:aad){ "hello there" }
63
+ before{ sub.attr_encrypted :with_aad, aad: aad }
64
+ it "encrypts the value with the given string for auth data" do
65
+ expect(cipher).to receive(:encrypt).with("hello", key: key, aad: aad)
66
+ subject.with_aad = "hello"
67
+ end
68
+
69
+ it "decrypts the encrypted value" do
70
+ subject.with_aad = "foo"
71
+ expect(subject.with_aad).to eq("foo")
72
+ end
73
+ end
74
+
75
+ context "that is nil" do
76
+ let(:aad){ nil }
77
+ before{ sub.attr_encrypted :with_aad, aad: aad }
78
+ it "encrypts the value with an empty string for auth data" do
79
+ expect(cipher).to receive(:encrypt).with("hello",key: key, aad: "").and_call_original
80
+ subject.with_aad = "hello"
81
+ end
82
+
83
+ it "decrypts the encrypted value" do
84
+ subject.with_aad = "hello"
85
+ expect(subject.with_aad).to eq("hello")
86
+ end
87
+ end
88
+
89
+ context "that is a proc" do
90
+ let(:aad){
91
+ proc{ |o| "x" }
92
+ }
93
+
94
+ before{ sub.attr_encrypted :with_aad, aad: aad }
95
+
96
+ it "calls the proc with the object being encrypted" do
97
+ expect(aad).to receive(:[]).with(subject).and_call_original
98
+ subject.with_aad = "hi"
99
+ end
100
+
101
+ it "encrypts the value with the string returned for auth data" do
102
+ expect(cipher).to receive(:encrypt).with("hello", key: key, aad: aad[subject]).and_call_original
103
+ subject.with_aad = "hello"
104
+ end
105
+ it "decrypts the encrypted value" do
106
+ subject.with_aad = "hello"
107
+ expect(subject.with_aad).to eq("hello")
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+
114
+ end
data/spec/key_spec.rb CHANGED
@@ -77,8 +77,8 @@ describe Slosilo::Key do
77
77
  end
78
78
  end
79
79
 
80
- let(:ciphertext) { "\x8B\xE6\xEC\x8C\xAB\xA4\xC0\x8EF\"\x0F\xD5Yh\xA1\aq\x00\xF5\xAC\xAB\v\a\xEC\xF6G\xA6\e\x14N\xFF\x11\x98\xDA\x19\xB5\x8994_:\xA0\xF8\x06l\xDC\x9B\xB1\xE8z\x83\xCC\x9A\x02E\x02tOhu\x92F]h".force_encoding("ASCII-8BIT") }
81
- let(:skey) { "\x15\xFF\xD4>\x9C\xF4\x0F\xB6\x04C\x18\xC1\x96\xC3\xE0T\xA3\xF5\xE8\x17\xA6\xE0\x86~rrw\xC3\xDF\x11)$\x9B\r@\x0E\xE4Zv\rw-\xFC\x1C\x84\x17\xBD\xDB\x12u\xCD\r\xFEo\xD5\xC8[\x8FEA\\\xA9\xA2F#\x8BH -\xFA\xF7\xA9\xEBf\x97\xAAT}\x8E*\xC0r\x944p\xD0\x9A\xE7\xBD\a;O\f\xEF\xE4B.y\xFA\xB4e@O\xBB\x15>y\xC9\t=\x01\xE1J\xF3X\xA9\x9E3\x04^H\x1F\xFF\x19C\x93ve)@\xF7\t_\xCF\xDE\xF1\xB7]\x83lL\xB8%A\x93p{\xE9Y\xBAu\xCE\x99T\xDC\xDF\xE7\x0FD%\xB9AXb\x1CW\x94$P\xBB\xE1g\xDEE\t\xC4\x92\x9E\xFEt\xDF\xD0\xEA\x03\xC4\x12\xA9\x02~u\xF4\x92 ;\xA0\xCE.\b+)\x05\xEDo\xA5cF\xF8\x12\xD7F\x97\xE44\xBF\xF1@\xA5\xC5\xA8\xE5\a\xE8ra<\x04\xB5\xA2\f\t\xF7T\x97\e\xF5(^\xAB\xA5%84\x10\xD1\x13e<\xCA/\xBF}%\xF6\xB1%\xB2".force_encoding("ASCII-8BIT") }
80
+ let(:ciphertext){ "G\xAD^\x17\x11\xBBQ9-b\x14\xF6\x92#Q0x\xF4\xAD\x1A\x92\xC3VZW\x89\x8E\x8Fg\x93\x05B\xF8\xD6O\xCFGCTp\b~\x916\xA3\x9AN\x8D\x961\x1F\xA3mSf&\xAD\xA77/]z\xA89\x01\xA7\xA9\x92\f".force_encoding('ASCII-8BIT') }
81
+ let(:skey){ "\x82\x93\xFAA\xA6wQA\xE1\xB5\xA6b\x8C.\xCF#I\x86I\x83u\x99\rTA\xEF\xC4\x91\xC5)-\xEBQ\xB1\xC0\xC6\xFF\x90L\xFE\x1E\x15\x81\x12\x16\xDD:A\xC5d\xE1B\xD2f@\xB8o\xB7+N\xB7\n\x92\xDC\x9E\xE3\x83\xB8>h\a\xC7\xCC\xCF\xD0t\x06\x8B\xA8\xBF\xEFe\xA4{\x88\f\xDD\roF\xEB.\xDA\xBF\x9D_0>\xF03c'\x1F!)*-\x19\x97\xAC\xD2\x1F(,6h\a\x93\xDB\x8E\x97\xF9\x1A\x11\x84\x11t\xD9\xB2\x85\xB0\x12\x7F\x03\x00O\x8F\xBE#\xFFb\xA5w\xF3g\xCF\xB4\xF2\xB7\xDBiA=\xA8\xFD1\xEC\xBF\xD7\x8E\xB6W>\x03\xACNBa\xBF\xFD\xC6\xB32\x8C\xE2\xF1\x87\x9C\xAE6\xD1\x12\vkl\xBB\xA0\xED\x9A\xEE6\xF2\xD9\xB4LL\xE2h/u_\xA1i=\x11x\x8DGha\x8EG\b+\x84[\x87\x8E\x01\x0E\xA5\xB0\x9F\xE9vSl\x18\xF3\xEA\xF4NH\xA8\xF1\x81\xBB\x98\x01\xE8p]\x18\x11f\xA3K\xA87c\xBB\x13X~K\xA2".force_encoding('ASCII-8BIT') }
82
82
  describe '#decrypt' do
83
83
  it "decrypts the symmetric key and then uses it to decrypt the ciphertext" do
84
84
  expect(subject.decrypt(ciphertext, skey)).to eq(plaintext)
@@ -3,34 +3,56 @@ require 'spec_helper'
3
3
  describe Slosilo::Symmetric do
4
4
  # TODO transform it to class methods only?
5
5
  let(:plaintext) { "quick brown fox jumped over the lazy dog" }
6
+ let(:auth_data) { "some record id" }
6
7
  let(:key) { "^\xBAIv\xDB1\x0Fi\x04\x11\xFD\x14\xA7\xCD\xDFf\x93\xFE\x93}\v\x01\x11\x98\x14\xE0;\xC1\xE2 v\xA5".force_encoding("ASCII-8BIT") }
7
- let(:iv) { "\xA1\xFA#z\x16\x80R\xCC|\x0Fyc\xB7j\x17\xED".force_encoding("ASCII-8BIT") }
8
- let(:ciphertext) { "\xA1\xFA#z\x16\x80R\xCC|\x0Fyc\xB7j\x17\xED\x15\xC9r\xC9\xEE\xB9\xBC5\xB7\ni\x0F\f\xC8X\x80 h\a\xF4\xA6\xE3\x15\x9D\xF1-\xE5\bs\xF6\x02Z\x0F\xCD|S\x1A\xAA\x9At\xEFT\x17\xA5lT\x8C\xF3".force_encoding("ASCII-8BIT") }
8
+ let(:iv) { "\xD9\xABn\x01b\xFA\xBD\xC2\xE5\xEA\x01\xAC".force_encoding("ASCII-8BIT") }
9
+ let(:ciphertext) { "G^W1\x9C\xD4\xCC\x87\xD3\xFF\x86[\x0E3\xC0\xC8^\xD9\xABn\x01b\xFA\xBD\xC2\xE5\xEA\x01\xAC\x9E\xB9:\xF7\xD4ebeq\xDC \xC0sG\xA4\xAE,\xB8A|\x97\xBC\xFD\x85\xE1\xB93\x95>\xBD\n\x05\xFB\x15\x1F\x06#3M9".force_encoding('ASCII-8BIT') }
10
+
9
11
  describe '#encrypt' do
10
- it "encrypts with AES-256-CBC" do
12
+ it "encrypts with AES-256-GCM" do
11
13
  allow(subject).to receive_messages random_iv: iv
12
- expect(subject.encrypt(plaintext, key: key)).to eq(ciphertext)
14
+ expect(subject.encrypt(plaintext, key: key, aad: auth_data)).to eq(ciphertext)
13
15
  end
14
16
  end
15
17
 
16
18
  describe '#decrypt' do
17
- it "decrypts with AES-256-CBC" do
18
- expect(subject.decrypt(ciphertext, key: key)).to eq(plaintext)
19
+ it "decrypts with AES-256-GCM" do
20
+ expect(subject.decrypt(ciphertext, key: key, aad: auth_data)).to eq(plaintext)
21
+ end
22
+
23
+
24
+ context "when the ciphertext has been messed with" do
25
+ let(:ciphertext) { "pwnd!" } # maybe we should do something more realistic like add some padding?
26
+ it "raises an exception" do
27
+ expect{ subject.decrypt(ciphertext, key: key, aad: auth_data)}.to raise_exception
28
+ end
29
+ context "by adding a trailing 0" do
30
+ let(:new_ciphertext){ ciphertext + '\0' }
31
+ it "raises an exception" do
32
+ expect{ subject.decrypt(new_ciphertext, key: key, aad: auth_data) }.to raise_exception
33
+ end
34
+ end
19
35
  end
20
-
21
- context "when ciphertext happens to end in a zero" do
22
- let(:ciphertext) { "\x7F\xD6\xEAb\xE56\a\xD3\xC5\xF2J\n\x8C\x8Fg\xB7-\\\x8A\fh\x18\xC8\x91\xB9 \x97\xC9\x12\xE6\xA6\xAE\xB1I\x1E\x80\xAB\xD8\xDC\xBD\xB6\xCD\x9A\xA3MH\xA8\xB0\xC7\xDA\x87\xA7c\xD75,\xD2A\xB8\x9E\xE3o\x04\x00" }
23
- let(:key) { "4pSuk1rAQyuHA5uUYaj0X0BsiPCFb9Nc8J03XA6V5/Y" }
24
- it "works correctly" do
25
- expect(subject.decrypt(ciphertext, key: key)).to eq("R6KNTQ4aUivojbaqhgAqj1I4PaF8h/5/YcENy4uNbfk=")
36
+
37
+ context "when no auth_data is given" do
38
+ let(:auth_data){""}
39
+ let(:ciphertext){ "Gm\xDAT\xE8I\x9F\xB7\xDC\xBB\x84\xD3Q#\x1F\xF4\x8C\aV\x93\x8F_\xC7\xBC87\xC9U\xF1\xAF\x8A\xD62\x1C5H\x86\x17\x19=B~Y*\xBC\x9D\eJeTx\x1F\x02l\t\t\xD3e\xA4\x11\x13y*\x95\x9F\xCD\xC4@\x9C"}
40
+
41
+ it "decrypts the message" do
42
+ expect(subject.decrypt(ciphertext, key: key, aad: auth_data)).to eq(plaintext)
43
+ end
44
+
45
+ context "and the ciphertext has been messed with" do
46
+ it "raises an exception" do
47
+ expect{ subject.decrypt(ciphertext + "\0\0\0", key: key, aad: auth_data)}.to raise_exception
48
+ end
26
49
  end
27
50
  end
28
51
 
29
- context "when the iv ends in space" do
30
- let(:ciphertext) { "\xC0\xDA#\xE9\xE1\xFD\xEDJ\xADs4P\xA9\xD6\x92 \xF7\xF8_M\xF6\x16\xC2i$\x8BT^\b\xA1\xB2L&\xE9\x80\x02[]6i\x9B\xD3\xC3\xED\xA9\xD1\x94\xE8\x15\xFD\xDA\xFEUj\xC5upH*\xBF\x82\x15le" }
31
- let(:key) { "4pSuk1rAQyuHA5uUYaj0X0BsiPCFb9Nc8J03XA6V5/Y" }
32
- it "works correctly" do
33
- expect(subject.decrypt(ciphertext, key: key)).to eq("zGptmL3vd4obi1vqSiWHt/Ias2k+6qDtuq9vdow8jNA=")
52
+ context "when the auth data doesn't match" do
53
+ let(:auth_data){ "asdf" }
54
+ it "raises an exception" do
55
+ expect{ subject.decrypt(ciphertext, key: key, aad: auth_data)}.to raise_exception
34
56
  end
35
57
  end
36
58
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slosilo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafał Rzepecki
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-20 00:00:00.000000000 Z
11
+ date: 2014-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -138,6 +138,7 @@ files:
138
138
  - lib/slosilo/version.rb
139
139
  - lib/tasks/slosilo.rake
140
140
  - slosilo.gemspec
141
+ - spec/encrypted_attributes_spec.rb
141
142
  - spec/file_adapter_spec.rb
142
143
  - spec/key_spec.rb
143
144
  - spec/keystore_spec.rb
@@ -166,11 +167,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
167
  version: '0'
167
168
  requirements: []
168
169
  rubyforge_project:
169
- rubygems_version: 2.2.2
170
+ rubygems_version: 2.0.14
170
171
  signing_key:
171
172
  specification_version: 4
172
173
  summary: Store SSL keys in a database
173
174
  test_files:
175
+ - spec/encrypted_attributes_spec.rb
174
176
  - spec/file_adapter_spec.rb
175
177
  - spec/key_spec.rb
176
178
  - spec/keystore_spec.rb