master-crypt 0.0.1 → 0.0.5

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
  SHA256:
3
- metadata.gz: 30c1cf54ea583219381fdbed0e73f77f1f4b7168fe7bf5e3a568832d50be208f
4
- data.tar.gz: 8add2b4b02dc45935f7317561b09e49a1e1bca477634a0bf3672ffaf8fc80a4c
3
+ metadata.gz: 9a11aff2304c6483147f3e7cc3d57996af1a4fd0ba730f10d3e130fec9730562
4
+ data.tar.gz: 86bfd58ddc3e941d344ea0ccb83ae608305ba86e5118243e19e47d9e306f1a20
5
5
  SHA512:
6
- metadata.gz: b9b16ea951a97dd3577962c54303ec46ab1e3c9df2bd890408a925a69f65f71a555139facefca207c32f87d82bf8a4984e20711a95c0de807fa085c2a1ec9dca
7
- data.tar.gz: d94abe5413f90b4a7cac2fcf875f834d6066904e0b2b36f3b3991a9123d89be19a19bd6b8484962a6ecf082b3c84bbab45bb06a825287498c12cc9aa41fdbd26
6
+ metadata.gz: 47d07d1d36a509892ee5cc4e05794233ef6d37c6f866896133a89abc92a0ed5af30dc2c1a7640925b71ff2f0dba5c52d378c66e3926d9c85cf5249df87ea663a
7
+ data.tar.gz: a8e56a738b7afc220129eb7bd7dd5762b10a8a8cf09285327917a83e68b2b167ee18725c903c2a232b4f4b67c16849aae64e9937817a11513ff9548d4a0a6bbb
data/README.md CHANGED
@@ -1,12 +1,88 @@
1
- # master-crypt
1
+ # Master Crypt
2
+
3
+ [![CircleCI](https://circleci.com/gh/cianmce/master-crypt.svg?style=shield)](https://circleci.com/gh/cianmce/master-crypt)
4
+
5
+ Master Key is a gem for encrypting data with a [master keying](https://en.wikipedia.org/wiki/Master_keying) approach
6
+
7
+ This allows you to have a master key to decrypt the full set of data while also creating keys that can only decrypt a subset of data. These keys can then be safely distributed to relevant actors who will be only able to access their permitted data
8
+
9
+ You can encrypt data with as many keys as needed, all of which will be able to decrypt the data while only causing a small encrypted data size increase of 129 bytes for each extra key
10
+
11
+
12
+ ## Installatio
13
+ ### Installing RbNaCl
14
+ https://github.com/RubyCrypto/rbnacl#installation
15
+
16
+ #### OS X users
17
+ ```sh
18
+ brew install libsodium
19
+ ```
20
+
21
+ #### FreeBSD users
22
+ ```sh
23
+ pkg install libsodium
24
+ ```
25
+
26
+ #### APT users
27
+
28
+ ```sh
29
+ apt install libsodium-dev
30
+ ```
31
+
32
+ ### Installing MasterCrypt
33
+ ```sh
34
+ gem install master_crypt
35
+ ```
36
+
37
+ ## Usage
38
+ ### Encrypting data with a master key
39
+ ```ruby
40
+ require "master_crypt"
41
+
42
+ master_key = "Very secure & random master k3y"
43
+ other_secret_key = "Another very secure & random other k3y"
44
+ plaintext = "Secret data..."
45
+ master_crypt = MasterCrypt.new(master_key)
46
+
47
+ encrypted_data = master_crypt.master_key_encrypt(plaintext, [other_secret_key])
48
+ # encrypted_data can be decrypted with either the master_key or other_secret_key
49
+ ```
50
+
51
+ ### Decrypting data with a master key
52
+ ```ruby
53
+ master_key = "Very secure & random master k3y"
54
+ encrypted_data = "...."
55
+ master_crypt = MasterCrypt.new(master_key)
56
+
57
+ plaintext = master_crypt.master_key_decrypt(encrypted_data)
58
+ ```
59
+
60
+ ### Encrypting data with an array of keys
61
+
62
+ ```ruby
63
+ secret_keys = ["array", "of", "secret", "keys"]
64
+ encrypted_data = MasterCrypt.encrypt(plaintext, secret_keys)
65
+ ```
66
+
67
+ ### Decrypting data with a specific key
68
+
69
+ ```ruby
70
+ MasterCrypt.decrypt(encrypted_data, secret_keys[0])
71
+ ```
2
72
 
3
73
  ## Development
4
74
  ```sh
5
75
  bundle install
6
76
  ```
7
77
 
8
- ### Specs
9
- Run a
78
+ ### Run all specs + standardrb
79
+
10
80
  ```sh
81
+ bundle exec rake
82
+ ```
11
83
 
84
+ ### Run specs using guard
85
+
86
+ ```sh
87
+ bundle exec guard
12
88
  ```
data/lib/master_crypt.rb CHANGED
@@ -3,11 +3,59 @@ require "rbnacl"
3
3
  require "base64"
4
4
  require "digest"
5
5
 
6
- module MasterCrypt
6
+ class MasterCrypt
7
+ class CryptoError < StandardError; end
8
+
9
+ # Create a new MasterCrypt object with a master key which
10
+ # is used in `master_key_encrypt` and `master_key_decrypt`
11
+ #
12
+ # @param [String] Master key
13
+ #
14
+ # @return [MasterCrypt] A MasterCrypt object with a stored master key
15
+ def initialize(master_key)
16
+ raise ArgumentError, "Master key must not be blank" if master_key.nil? || master_key.empty?
17
+ @master_key = master_key
18
+ end
19
+
20
+ # Encrypts plaintext data with the master key and an optional
21
+ # list of additional secret keys
22
+ #
23
+ # @param plaintext [String] Plaintext data to be encrypted
24
+ # @param secret_keys [Array<String>] Optional list of
25
+ # additional secret keys to be used for encrypting data
26
+ #
27
+ # @return [String] Base64 representation of encrypted data
28
+ #
29
+ # @raise [ArgumentError] When secret keys are missing or blank
30
+ def master_key_encrypt(plaintext, secret_keys = [])
31
+ self.class.encrypt(plaintext, [@master_key] + Array(secret_keys))
32
+ end
33
+
34
+ # Decrypts encrypted data with the master key
35
+ #
36
+ # @param encrypted_data [String] Base64 representation of encrypted data
37
+ #
38
+ # @return [String] Decrypted plaintext data
39
+ #
40
+ # @raise [MasterCrypt::CryptoError] When master key or encrypted data is invalid
41
+ def master_key_decrypt(encrypted_data)
42
+ self.class.decrypt(encrypted_data, @master_key)
43
+ end
44
+
7
45
  class << self
8
- def encrypt(plaintext, secrets)
9
- raise "Secrets must not be blank" unless secrets.select(&:empty?).empty?
10
- raise "At least 1 secret is required" if !secrets.is_a?(Array) || secrets.empty?
46
+ # Encrypts plaintext data with a list of secret keys
47
+ #
48
+ # @param plaintext [String] Plaintext data to be encrypted
49
+ # @param secret_keys [Array<String>] A list of secret keys to be used for encrypting data
50
+ #
51
+ # @return [String] Base64 representation of encrypted data
52
+ #
53
+ # @raise [ArgumentError] When secret keys are missing or blank
54
+ def encrypt(plaintext, secret_keys)
55
+ raise ArgumentError, "At least 1 secret key is required" if !secret_keys.is_a?(Array) || secret_keys.empty?
56
+ raise ArgumentError, "Secret keys must not be blank" unless secret_keys.select(&:empty?).empty?
57
+ # there's no point in using the same key multiple times
58
+ secret_keys.uniq!
11
59
 
12
60
  random_key = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes)
13
61
  # encrypt data with random_key
@@ -17,7 +65,7 @@ module MasterCrypt
17
65
  encrypted_data64 = Base64.strict_encode64(encrypted_data)
18
66
 
19
67
  # encrypt random_kets with each secret
20
- encrypted_random_keys64 = secrets.collect do |secret|
68
+ encrypted_random_keys64 = secret_keys.collect do |secret|
21
69
  key = generate_key_from_secret(secret)
22
70
  box = RbNaCl::SimpleBox.from_secret_key(key)
23
71
 
@@ -29,16 +77,26 @@ module MasterCrypt
29
77
  Base64.strict_encode64(encrypted_data64 + "|" + encrypted_random_keys64.join(":"))
30
78
  end
31
79
 
32
- def decrypt(encrypted_data, secret)
80
+ # Decrypts encrypted data with a provided secret key
81
+ #
82
+ # @param encrypted_data [String] Base64 representation of encrypted data
83
+ # @param secret_key [String] Secret key to be used to decrypt data
84
+ #
85
+ # @return [String] Decrypted plaintext data
86
+ #
87
+ # @raise [MasterCrypt::CryptoError] When secret key or encrypted data is invalid
88
+ def decrypt(encrypted_data, secret_key)
33
89
  encrypted_data64, encrypted_random_keys64_joined = Base64.strict_decode64(encrypted_data).split("|", 2)
34
90
 
35
91
  encrypted_random_keys64 = encrypted_random_keys64_joined.split(":")
36
- key = find_key(encrypted_random_keys64, secret)
92
+ key = find_key(encrypted_random_keys64, secret_key)
37
93
 
38
94
  box = RbNaCl::SimpleBox.from_secret_key(key)
39
95
 
40
96
  ciphertext = Base64.strict_decode64(encrypted_data64)
41
97
  box.decrypt(ciphertext).force_encoding(Encoding::UTF_8)
98
+ rescue RbNaCl::CryptoError => e
99
+ raise CryptoError, e.message
42
100
  end
43
101
 
44
102
  private
@@ -55,7 +113,7 @@ module MasterCrypt
55
113
  rescue RbNaCl::CryptoError
56
114
  end
57
115
  end
58
- raise "No valid key for '#{secret}'"
116
+ raise CryptoError, "Invalid secret key '#{secret}'"
59
117
  end
60
118
 
61
119
  def generate_key_from_secret(secret)
@@ -1,3 +1,3 @@
1
- module MasterCrypt
2
- VERSION = "0.0.1"
1
+ class MasterCrypt
2
+ VERSION = "0.0.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: master-crypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cian McElhinney
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-01 00:00:00.000000000 Z
11
+ date: 2021-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: standardrb
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '2.2'
33
+ version: '1'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '2.2'
40
+ version: '1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -70,86 +70,86 @@ dependencies:
70
70
  name: pry
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: 0.13.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: 0.13.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: pry-byebug
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '3.9'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '3.9'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: pry-doc
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '1.1'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '1.1'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: guard
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '2.18'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '2.18'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: guard-rspec
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ">="
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: 4.7.3
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ">="
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: 4.7.3
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: rbnacl
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - '='
143
+ - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 7.1.1
145
+ version: '7.0'
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - '='
150
+ - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 7.1.1
152
+ version: '7.0'
153
153
  description: Allows for encrypting a single piece of data with multiple keys which
154
154
  can each be used to decrypt it
155
155
  email:
@@ -176,7 +176,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
176
  requirements:
177
177
  - - ">="
178
178
  - !ruby/object:Gem::Version
179
- version: '0'
179
+ version: 2.3.0
180
180
  required_rubygems_version: !ruby/object:Gem::Requirement
181
181
  requirements:
182
182
  - - ">="