master-crypt 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d66fc7a3d34de5271f109f302daad32070724869cece105c062a844ae3bcc405
4
- data.tar.gz: '06158f18251f6157085123568ee9818e46fea1e1f4dbf2db89f1f8293b7b7d6e'
3
+ metadata.gz: feb8bc6283d255c63b665645b2380b97a424973674b68c5e43ca1148d2104539
4
+ data.tar.gz: a5d4a0bd894035a9b099936a910210010c5de652574bb90fd0bc6e2fa3080480
5
5
  SHA512:
6
- metadata.gz: da0d0b57b077b38d0e478d6940cf5c9de72b376cb8e9efbdccd0afefc04fabc1348fdf08ea014521ed3f2d747ed0afa240f027cd6fa8a26b090793e2a7804fb9
7
- data.tar.gz: 3fabf752a22e46befa105e815e86964e1842c68e5d46f3d89c84f4a79be729103e893317c32d690999f28c6279c78aa5b5d39a377b76550caae35f2ba74a190c
6
+ metadata.gz: eb0ac83c13620f593102d8390376a692ef7a4a2fa8b4c7c8dd58da879d1b032cb3e9bf4821c28b72a115ca7ab8bb0de87b23c250d45b61ffb1feffa9c73281a4
7
+ data.tar.gz: 9da6ba87ab3b7eb58fc4be0e933d74d4fdbfc03c388cc7dd3508963eacefc044e52aa1c2ba6ef74ccbc95bca014ba107afe5a77d38b27b509aaebc6aae8954c9
data/README.md CHANGED
@@ -1,15 +1,50 @@
1
- # master-crypt
1
+ # Master Crypt
2
2
 
3
- ## Usage
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
+ ```
4
36
 
37
+ ## Usage
5
38
  ### Encrypting data with a master key
6
39
  ```ruby
40
+ require "master_crypt"
41
+
7
42
  master_key = "Very secure & random master k3y"
8
- other_secret_key = "Another very secure & random master k3y"
9
- data = "Secret data..."
43
+ other_secret_key = "Another very secure & random other k3y"
44
+ plaintext = "Secret data..."
10
45
  master_crypt = MasterCrypt.new(master_key)
11
46
 
12
- encrypted_data = master_crypt.master_key_encrypt(data, [other_secret_key])
47
+ encrypted_data = master_crypt.master_key_encrypt(plaintext, [other_secret_key])
13
48
  # encrypted_data can be decrypted with either the master_key or other_secret_key
14
49
  ```
15
50
 
@@ -22,13 +57,24 @@ master_crypt = MasterCrypt.new(master_key)
22
57
  plaintext = master_crypt.master_key_decrypt(encrypted_data)
23
58
  ```
24
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
+ ```
72
+
25
73
  ## Development
26
74
  ```sh
27
75
  bundle install
28
76
  ```
29
77
 
30
- ## Specs
31
-
32
78
  ### Run all specs + standardrb
33
79
 
34
80
  ```sh
data/lib/master_crypt.rb CHANGED
@@ -4,23 +4,58 @@ require "base64"
4
4
  require "digest"
5
5
 
6
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
7
15
  def initialize(master_key)
8
- raise "Master key must not be blank" if master_key.nil? || master_key.empty?
16
+ raise ArgumentError, "Master key must not be blank" if master_key.nil? || master_key.empty?
9
17
  @master_key = master_key
10
18
  end
11
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
12
30
  def master_key_encrypt(plaintext, secret_keys = [])
13
31
  self.class.encrypt(plaintext, [@master_key] + Array(secret_keys))
14
32
  end
15
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
16
41
  def master_key_decrypt(encrypted_data)
17
42
  self.class.decrypt(encrypted_data, @master_key)
18
43
  end
19
44
 
20
45
  class << self
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
21
54
  def encrypt(plaintext, secret_keys)
22
- raise "At least 1 secret key is required" if !secret_keys.is_a?(Array) || secret_keys.empty?
23
- raise "Secret keys must not be blank" unless secret_keys.select(&:empty?).empty?
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!
24
59
 
25
60
  random_key = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes)
26
61
  # encrypt data with random_key
@@ -42,16 +77,26 @@ class MasterCrypt
42
77
  Base64.strict_encode64(encrypted_data64 + "|" + encrypted_random_keys64.join(":"))
43
78
  end
44
79
 
45
- 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)
46
89
  encrypted_data64, encrypted_random_keys64_joined = Base64.strict_decode64(encrypted_data).split("|", 2)
47
90
 
48
91
  encrypted_random_keys64 = encrypted_random_keys64_joined.split(":")
49
- key = find_key(encrypted_random_keys64, secret)
92
+ key = find_key(encrypted_random_keys64, secret_key)
50
93
 
51
94
  box = RbNaCl::SimpleBox.from_secret_key(key)
52
95
 
53
96
  ciphertext = Base64.strict_decode64(encrypted_data64)
54
97
  box.decrypt(ciphertext).force_encoding(Encoding::UTF_8)
98
+ rescue RbNaCl::CryptoError => e
99
+ raise CryptoError, e.message
55
100
  end
56
101
 
57
102
  private
@@ -68,7 +113,7 @@ class MasterCrypt
68
113
  rescue RbNaCl::CryptoError
69
114
  end
70
115
  end
71
- raise "No valid key for '#{secret}'"
116
+ raise CryptoError, "Invalid secret key '#{secret}'"
72
117
  end
73
118
 
74
119
  def generate_key_from_secret(secret)
@@ -1,3 +1,3 @@
1
1
  class MasterCrypt
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
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.3
4
+ version: 0.0.4
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-03 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