ribbon-encrypted_store 0.1.5 → 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ed9c1b5768713771553fc0ae858ba9230f12e7a
|
4
|
+
data.tar.gz: 4ca77eb35ee661056d33ad308f9a6132b7ea94d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1abc59705a77c7d009823b388681a4e004a472308b6885012e6af6b59b65deeabc09daeddf56594e30affb21de333679bbf7cf84c4157b79d981acb0fa399551
|
7
|
+
data.tar.gz: b626cd351cdffbb155cebdc9c43fc30fed4f6e18c630e32c91ef4106a88ce289e325e5a04f62e9ee40f7784a3ca12d06a1adde53c614ed7bf61c9c5b75cd40bb
|
@@ -11,32 +11,31 @@ module Ribbon::EncryptedStore
|
|
11
11
|
|
12
12
|
##
|
13
13
|
# Encrypts the hash using the data encryption key and salt.
|
14
|
-
# Returns a blob:
|
15
|
-
#
|
16
|
-
# | Byte 0 | Byte 1 | Bytes 2...S | Bytes S+1...E | Bytes E+1..E+4 |
|
17
|
-
# --------------------------------------------------------------------------
|
18
|
-
# | Version | Salt Length | Salt | Encrypted Data | CRC32 |
|
19
14
|
#
|
20
|
-
|
15
|
+
# Returns a blob:
|
16
|
+
# | Byte 0 | Byte 1 | Byte 2 | Bytes 3...S | Bytes S+1...E | Bytes E+1..E+4 |
|
17
|
+
# ------------------------------------------------------------------------------------------------
|
18
|
+
# | Version | Salt Length | Iteration Magnitude | Salt | Encrypted Data | CRC32 |
|
19
|
+
def encrypt(dek, salt, iter_mag=10)
|
21
20
|
return nil if empty?
|
22
|
-
raise Errors::
|
21
|
+
raise Errors::InvalidSaltSize, 'too long' if salt.bytes.length > 255
|
23
22
|
|
24
|
-
key, iv = _keyiv_gen(dek, salt)
|
23
|
+
key, iv = _keyiv_gen(dek, salt, iter_mag)
|
25
24
|
|
26
25
|
encryptor = OpenSSL::Cipher::AES256.new(:CBC).encrypt
|
27
26
|
encryptor.key = key
|
28
27
|
encryptor.iv = iv
|
29
28
|
|
30
|
-
data_packet =
|
29
|
+
data_packet = _encrypted_data_header_v2(salt, iter_mag) + encryptor.update(self.to_json) + encryptor.final
|
31
30
|
_append_crc32(data_packet)
|
32
31
|
end
|
33
32
|
|
34
33
|
class << self
|
35
34
|
def decrypt(dek, data)
|
36
35
|
return CryptoHash.new unless data
|
37
|
-
salt, data = _split_binary_data(data)
|
36
|
+
salt, iter_mag, data = _split_binary_data(data)
|
38
37
|
|
39
|
-
key, iv = _keyiv_gen(dek, salt)
|
38
|
+
key, iv = _keyiv_gen(dek, salt, iter_mag)
|
40
39
|
|
41
40
|
decryptor = OpenSSL::Cipher::AES256.new(:CBC).decrypt
|
42
41
|
decryptor.key = key
|
@@ -47,12 +46,18 @@ module Ribbon::EncryptedStore
|
|
47
46
|
CryptoHash.new(new_hash)
|
48
47
|
end
|
49
48
|
|
50
|
-
def _keyiv_gen(key, salt)
|
51
|
-
|
52
|
-
|
49
|
+
def _keyiv_gen(key, salt, iter_mag)
|
50
|
+
if iter_mag == -1
|
51
|
+
raise Errors::InvalidKeySize, 'must be exactly 256 bits' unless key.bytes.length == 32
|
52
|
+
raise Errors::InvalidSaltSize, 'must be exactly 128 bits' unless salt.bytes.length == 16
|
53
|
+
iv = salt
|
54
|
+
else
|
55
|
+
digest = OpenSSL::Digest::SHA256.new
|
56
|
+
key_and_iv = OpenSSL::PKCS5.pbkdf2_hmac(key, salt, 1 << iter_mag, 48, digest)
|
53
57
|
|
54
|
-
|
55
|
-
|
58
|
+
key = key_and_iv[0..31]
|
59
|
+
iv = key_and_iv[32..-1]
|
60
|
+
end
|
56
61
|
|
57
62
|
[key, iv]
|
58
63
|
end
|
@@ -61,7 +66,18 @@ module Ribbon::EncryptedStore
|
|
61
66
|
# Split encrypted data and CRC
|
62
67
|
bytes = encrypted_data.bytes
|
63
68
|
|
64
|
-
version
|
69
|
+
version = bytes[0]
|
70
|
+
version_method = "_split_binary_data_v#{version}"
|
71
|
+
|
72
|
+
if respond_to?(version_method)
|
73
|
+
send(version_method, encrypted_data)
|
74
|
+
else
|
75
|
+
raise Errors::UnsupportedVersionError, "Unsupported encrypted data version: #{version}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def _split_binary_data_v1(encrypted_data)
|
80
|
+
bytes = encrypted_data.bytes
|
65
81
|
salt_length = bytes[1]
|
66
82
|
|
67
83
|
salt_start_index = 2
|
@@ -72,9 +88,26 @@ module Ribbon::EncryptedStore
|
|
72
88
|
crc = bytes[-4..-1]
|
73
89
|
raise Errors::ChecksumFailedError unless crc == _calc_crc32(encrypted_data[0..-5]).bytes
|
74
90
|
|
75
|
-
[salt, data]
|
91
|
+
[salt, 12, data]
|
92
|
+
end
|
93
|
+
|
94
|
+
def _split_binary_data_v2(encrypted_data)
|
95
|
+
bytes = encrypted_data.bytes
|
96
|
+
salt_length = bytes[1]
|
97
|
+
iter_mag = bytes[2].chr.unpack('c').first
|
98
|
+
|
99
|
+
salt_start_index = 3
|
100
|
+
salt_end_index = salt_start_index + salt_length - 1
|
101
|
+
salt = bytes[salt_start_index..salt_end_index].pack('c*')
|
102
|
+
data = bytes[salt_end_index+1..-5].pack('c*')
|
103
|
+
|
104
|
+
crc = bytes[-4..-1]
|
105
|
+
raise Errors::ChecksumFailedError unless crc == _calc_crc32(encrypted_data[0..-5]).bytes
|
106
|
+
|
107
|
+
[salt, iter_mag, data]
|
76
108
|
end
|
77
109
|
|
110
|
+
|
78
111
|
def _calc_crc32(data)
|
79
112
|
[Zlib.crc32(data)].pack('N')
|
80
113
|
end
|
@@ -83,17 +116,27 @@ module Ribbon::EncryptedStore
|
|
83
116
|
private
|
84
117
|
|
85
118
|
##
|
86
|
-
# Generates the encrypted data header:
|
119
|
+
# Generates the version 1 encrypted data header:
|
87
120
|
# | Byte 0 | Byte 1 | Bytes 2...S
|
88
121
|
# ---------------------------------------------------
|
89
122
|
# | Version | Salt Length | Salt
|
90
123
|
#
|
91
|
-
def
|
124
|
+
def _encrypted_data_header_v1(salt)
|
92
125
|
"\x01" + salt.bytes.length.chr + salt
|
93
126
|
end
|
94
127
|
|
95
|
-
|
96
|
-
|
128
|
+
##
|
129
|
+
# Generates the version 2 encrypted data header:
|
130
|
+
# | Byte 0 | Byte 1 | Byte 2 | Bytes 3...S
|
131
|
+
# ----------------------------------------------------------------------
|
132
|
+
# | Version | Salt Length | Iteration Magnitude | Salt
|
133
|
+
#
|
134
|
+
def _encrypted_data_header_v2(salt, iter_mag)
|
135
|
+
"\x02" + salt.bytes.length.chr + [iter_mag].pack('c') + salt
|
136
|
+
end
|
137
|
+
|
138
|
+
def _keyiv_gen(key, salt, iter_mag)
|
139
|
+
self.class._keyiv_gen(key, salt, iter_mag)
|
97
140
|
end
|
98
141
|
|
99
142
|
def _append_crc32(data)
|
@@ -9,6 +9,8 @@ module Ribbon::EncryptedStore
|
|
9
9
|
# CryptoHash Errors
|
10
10
|
class CryptoHashError < Error; end
|
11
11
|
class ChecksumFailedError < CryptoHashError; end
|
12
|
-
class
|
12
|
+
class InvalidSaltSize < CryptoHashError; end
|
13
|
+
class InvalidKeySize < CryptoHashError; end
|
14
|
+
class UnsupportedVersionError < CryptoHashError; end
|
13
15
|
end # Errors
|
14
|
-
end # Ribbon::EncryptedStore
|
16
|
+
end # Ribbon::EncryptedStore
|
@@ -35,7 +35,7 @@ module Ribbon::EncryptedStore
|
|
35
35
|
|
36
36
|
def attr_encrypted(*args)
|
37
37
|
# Store attrs in class data
|
38
|
-
_encrypted_store_data[:encrypted_attributes] = args
|
38
|
+
_encrypted_store_data[:encrypted_attributes] = args.map(&:to_sym)
|
39
39
|
|
40
40
|
args.each { |arg|
|
41
41
|
define_method(arg) { _encrypted_store_get(arg) }
|
@@ -83,7 +83,7 @@ module Ribbon::EncryptedStore
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def _encrypted_store_save
|
86
|
-
if !(self.changed & _encrypted_store_data[:encrypted_attributes]).empty? || @_reencrypting
|
86
|
+
if !(self.changed.map(&:to_sym) & _encrypted_store_data[:encrypted_attributes]).empty? || @_reencrypting
|
87
87
|
# Obtain a lock without overriding attribute values for this record.
|
88
88
|
record = self.class.unscoped { self.class.lock.find(id) } unless new_record?
|
89
89
|
|
@@ -91,8 +91,16 @@ module Ribbon::EncryptedStore
|
|
91
91
|
self.encryption_key_id = record.encryption_key_id if record && record.encryption_key_id
|
92
92
|
end
|
93
93
|
|
94
|
+
iter_mag = Ribbon::EncryptedStore.config.iteration_magnitude? ?
|
95
|
+
Ribbon::EncryptedStore.config.iteration_magnitude :
|
96
|
+
-1
|
97
|
+
|
94
98
|
@_reencrypting = false
|
95
|
-
self.encrypted_store = _crypto_hash.encrypt(
|
99
|
+
self.encrypted_store = _crypto_hash.encrypt(
|
100
|
+
_decrypted_key,
|
101
|
+
EncryptionKeySalt.generate_salt(_encryption_key_id),
|
102
|
+
iter_mag
|
103
|
+
)
|
96
104
|
end
|
97
105
|
end
|
98
106
|
end # ActiveRecordMixin
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ribbon-encrypted_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Honer
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-10-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bcrypt
|