master-crypt 0.0.3 → 0.0.4

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: 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