diffcrypt 0.3.3 → 0.4.0

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: 9e77d7111ad066e219da5f2c20dd2930bdda46641aa477bd3ab03e6194e19695
4
- data.tar.gz: 6af61a30f44c3c18ff92e7dac0564fbbb8ea6384740835d15f84c88eb200c9e5
3
+ metadata.gz: e40a357c62cf93d9c49f336c7ad456d4f7510bd8389f3fb20c4913b91f4ef5f2
4
+ data.tar.gz: 4fb0296c2eaf901c59bdec117f974203500596f6347a9b8c12632b7dbe39ab77
5
5
  SHA512:
6
- metadata.gz: 2c28fd4f218a5dafc07074b38f0b7b772b1cbd0eec06fee19a51e3b1f65ef048c8df0fa43ada8a785c166f03e0db21cf0534ff6586c010f916e2f7814a1dec5f
7
- data.tar.gz: a8e8130402e6a7aff0eb169a3498a33bc64fe383cd1a85742f4efb18ed2861fbaa335ae30109c9ba30fc298df55fd937f118370a8d58ce41d4c46fcb9ad75b75
6
+ metadata.gz: d368c674a915b706b876a5a022c7003e3f7ecf30b38b581f2e7debf261d47102d759c27d317b85a71904bace22fd1a0306d9175b2c9496592375d786d3fe4fc1
7
+ data.tar.gz: 9e24c98075aab9c2f8e0550e757adea3df5b7f1e341f7d93d5644ee21e6a9ee9a352f7450a1a63afd609d876406c6efbe4aaff56e6c978c413259588625eedf5
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
 
9
9
 
10
+ ## [0.4.0] - 2020-10-01
11
+
12
+ ### Changed
13
+
14
+ - Encryptor can now use other ciphers than the default
15
+
16
+ ### Dependencies
17
+
18
+ - simplecov: 0.17.0 -> 0.18.0 (#20)
19
+ - rubocop: 0.88.0 -> 0.92.0 (#24)
20
+
21
+
22
+
10
23
  ## [0.3.3] - 2020-07-25
11
24
 
12
25
  ### Fixed
data/Gemfile CHANGED
@@ -7,6 +7,6 @@ gemspec
7
7
 
8
8
  gem 'minitest', '~> 5.0'
9
9
  gem 'rake', '~> 13.0'
10
- gem 'rubocop', '~> 0.88.0'
11
- gem 'simplecov', '~> 0.17.0', require: false # CodeClimate not compatible with 0.18+ yet - https://github.com/codeclimate/test-reporter/issues/413
10
+ gem 'rubocop', '~> 0.92.0'
11
+ gem 'simplecov', '~> 0.19.0', require: false # CodeClimate not compatible with 0.18+ yet - https://github.com/codeclimate/test-reporter/issues/413
12
12
  gem 'simplecov-lcov', '< 0.8'
data/README.md CHANGED
@@ -36,8 +36,8 @@ There are a few ways to use the library, depending on how advanced your use case
36
36
  The easiest way to get started is to use the CLI.
37
37
 
38
38
  ```shell
39
- diffcrypt decrypt -k $(cat test/fixtures/master.key) test/fixtures/example.yml.enc
40
- diffcrypt encrypt -k $(cat test/fixtures/master.key) test/fixtures/example.yml
39
+ diffcrypt decrypt -k $(cat test/fixtures/aes-128-gcm.key) test/fixtures/example.yml.enc
40
+ diffcrypt encrypt -k $(cat test/fixtures/aes-128-gcm.key) test/fixtures/example.yml
41
41
  ```
42
42
 
43
43
 
@@ -69,7 +69,7 @@ the built in encrypter. All existing `rails credentials:edit` also work with thi
69
69
  require 'diffcrypt/rails/encrypted_configuration'
70
70
  module Rails
71
71
  class Application
72
- def encrypted(path, key_path: 'config/master.key', env_key: 'RAILS_MASTER_KEY')
72
+ def encrypted(path, key_path: 'config/aes-128-gcm.key', env_key: 'RAILS_MASTER_KEY')
73
73
  Diffcrypt::Rails::EncryptedConfiguration.new(
74
74
  config_path: Rails.root.join(path),
75
75
  key_path: Rails.root.join(key_path),
@@ -83,6 +83,17 @@ end
83
83
 
84
84
 
85
85
 
86
+ ## Converting between ciphers
87
+
88
+ Sometimes you may want to rotate the cipher used on a file. You cab do this rogramtically using the ruby code above, or you can also chain the CLI commands like so:
89
+
90
+ ```shell
91
+ diffcrypt decrypt -k $(cat test/fixtures/aes-128-gcm.key) test/fixtures/example.yml.enc > test/fixtures/example.128.yml \
92
+ && diffcrypt encrypt --cipher aes-256-gcm -k $(cat test/fixtures/aes-256-gcm.key) test/fixtures/example.128.yml > test/fixtures/example.256.yml.enc && rm test/fixtures/example.128.yml
93
+ ```
94
+
95
+
96
+
86
97
  ## Development
87
98
 
88
99
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  # Specify which files should be added to the gem when it is released.
24
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ spec.files = Dir.chdir(::File.expand_path(__dir__)) do
26
26
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
27
  end
28
28
  spec.bindir = 'bin'
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative './encryptor'
4
+ require_relative './file'
4
5
  require_relative './version'
5
6
 
6
7
  module Diffcrypt
@@ -8,21 +9,22 @@ module Diffcrypt
8
9
  desc 'decrypt <path>', 'Decrypt a file'
9
10
  method_option :key, aliases: %i[k], required: true
10
11
  def decrypt(path)
11
- ensure_file_exists(path)
12
- contents = File.read(path)
13
- puts encryptor.decrypt(contents)
12
+ file = File.new(path)
13
+ ensure_file_exists(file)
14
+ say file.decrypt(key)
14
15
  end
15
16
 
16
17
  desc 'encrypt <path>', 'Encrypt a file'
17
18
  method_option :key, aliases: %i[k], required: true
19
+ method_option :cipher, default: Encryptor::DEFAULT_CIPHER
18
20
  def encrypt(path)
19
- ensure_file_exists(path)
20
- contents = File.read(path)
21
- puts encryptor.encrypt(contents)
21
+ file = File.new(path)
22
+ ensure_file_exists(file)
23
+ say file.encrypt(key, cipher: options[:cipher])
22
24
  end
23
25
 
24
26
  desc 'generate-key', 'Generate a 32 bit key'
25
- method_option :cipher, default: Encryptor::CIPHER
27
+ method_option :cipher, default: Encryptor::DEFAULT_CIPHER
26
28
  def generate_key
27
29
  say Encryptor.generate_key(options[:cipher])
28
30
  end
@@ -41,8 +43,9 @@ module Diffcrypt
41
43
  @encryptor ||= Encryptor.new(key)
42
44
  end
43
45
 
44
- def ensure_file_exists(path)
45
- abort('[ERROR] File does not exist') unless File.exist?(path)
46
+ # @param [Diffcrypt::File] path
47
+ def ensure_file_exists(file)
48
+ abort('[ERROR] File does not exist') unless file.exists?
46
49
  end
47
50
 
48
51
  def self.exit_on_failure?
@@ -12,15 +12,16 @@ require_relative './version'
12
12
 
13
13
  module Diffcrypt
14
14
  class Encryptor
15
- CIPHER = 'aes-128-gcm'
15
+ DEFAULT_CIPHER = 'aes-128-gcm'
16
16
 
17
- def self.generate_key(cipher = CIPHER)
17
+ def self.generate_key(cipher = DEFAULT_CIPHER)
18
18
  SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(cipher))
19
19
  end
20
20
 
21
- def initialize(key)
21
+ def initialize(key, cipher: DEFAULT_CIPHER)
22
22
  @key = key
23
- @encryptor ||= ActiveSupport::MessageEncryptor.new([key].pack('H*'), cipher: CIPHER)
23
+ @cipher = cipher
24
+ @encryptor ||= ActiveSupport::MessageEncryptor.new([key].pack('H*'), cipher: cipher)
24
25
  end
25
26
 
26
27
  # @param [String] contents The raw YAML string to be encrypted
@@ -50,7 +51,7 @@ module Diffcrypt
50
51
  data = encrypt_data contents, original_encrypted_contents
51
52
  YAML.dump(
52
53
  'client' => "diffcrypt-#{Diffcrypt::VERSION}",
53
- 'cipher' => CIPHER,
54
+ 'cipher' => @cipher,
54
55
  'data' => data,
55
56
  )
56
57
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './encryptor'
4
+
5
+ module Diffcrypt
6
+ class File
7
+ attr_reader :file
8
+
9
+ def initialize(path)
10
+ @path = ::File.absolute_path path
11
+ end
12
+
13
+ def encrypted?
14
+ to_yaml['cipher']
15
+ end
16
+
17
+ def cipher
18
+ to_yaml['cipher'] || Encryptor::DEFAULT_CIPHER
19
+ end
20
+
21
+ # @return [Boolean]
22
+ def exists?
23
+ ::File.exist?(@path)
24
+ end
25
+
26
+ # @return [String] Raw contents of the file
27
+ def read
28
+ @read ||= ::File.read(@path)
29
+ end
30
+
31
+ def encrypt(key, cipher: DEFAULT_CIPHER)
32
+ return read if encrypted?
33
+
34
+ Encryptor.new(key, cipher: cipher).encrypt(read)
35
+ end
36
+
37
+ # TODO: Add a test to verify this does descrypt properly
38
+ def decrypt(key)
39
+ return read unless encrypted?
40
+
41
+ Encryptor.new(key, cipher: cipher).decrypt(read)
42
+ end
43
+
44
+ def to_yaml
45
+ @to_yaml ||= YAML.safe_load(read)
46
+ end
47
+ end
48
+ end
@@ -9,6 +9,8 @@ require 'active_support/core_ext/hash'
9
9
  require 'active_support/core_ext/module/delegation'
10
10
  require 'active_support/core_ext/object/inclusion'
11
11
 
12
+ require 'diffcrypt/file'
13
+
12
14
  module Diffcrypt
13
15
  module Rails
14
16
  class EncryptedConfiguration
@@ -21,13 +23,13 @@ module Diffcrypt
21
23
  delegate_missing_to :options
22
24
 
23
25
  def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
24
- @content_path = Pathname.new(File.absolute_path(config_path)).yield_self do |path|
26
+ @content_path = Pathname.new(::File.absolute_path(config_path)).yield_self do |path|
25
27
  path.symlink? ? path.realpath : path
26
28
  end
29
+ @diffcrypt_file = Diffcrypt::File.new(@content_path)
27
30
  @key_path = Pathname.new(key_path)
28
31
  @env_key = env_key
29
32
  @raise_if_missing_key = raise_if_missing_key
30
- @active_support_encryptor = ActiveSupport::MessageEncryptor.new([key].pack('H*'), cipher: Encryptor::CIPHER)
31
33
  end
32
34
 
33
35
  # Determines if file is using the diffable format, or still
@@ -73,7 +75,7 @@ module Diffcrypt
73
75
  # rubocop:disable Metrics/AbcSize
74
76
  def writing(contents)
75
77
  tmp_file = "#{Process.pid}.#{content_path.basename.to_s.chomp('.enc')}"
76
- tmp_path = Pathname.new File.join(Dir.tmpdir, tmp_file)
78
+ tmp_path = Pathname.new ::File.join(Dir.tmpdir, tmp_file)
77
79
  tmp_path.binwrite contents
78
80
 
79
81
  yield tmp_path
@@ -103,9 +105,18 @@ module Diffcrypt
103
105
  end
104
106
  end
105
107
 
108
+ # Rails applications with an existing credentials file, the inbuilt active support encryptor should be used
109
+ # @return [ActiveSupport::MessageEncryptor]
110
+ def active_support_encryptor
111
+ @active_support_encryptor = ActiveSupport::MessageEncryptor.new(
112
+ [key].pack('H*'),
113
+ cipher: @diffcrypt_file.cipher,
114
+ )
115
+ end
116
+
106
117
  # @return [Encryptor]
107
118
  def encryptor
108
- @encryptor ||= Encryptor.new key
119
+ @encryptor ||= Encryptor.new key, cipher: @diffcrypt_file.cipher
109
120
  end
110
121
 
111
122
  def read_env_key
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Diffcrypt
4
- VERSION = '0.3.3'
4
+ VERSION = '0.4.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diffcrypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc Qualie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-25 00:00:00.000000000 Z
11
+ date: 2020-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -70,8 +70,10 @@ files:
70
70
  - lib/diffcrypt.rb
71
71
  - lib/diffcrypt/cli.rb
72
72
  - lib/diffcrypt/encryptor.rb
73
+ - lib/diffcrypt/file.rb
73
74
  - lib/diffcrypt/rails/encrypted_configuration.rb
74
75
  - lib/diffcrypt/version.rb
76
+ - tmp/.keep
75
77
  homepage: https://github.com/marcqualie/diffcrypt
76
78
  licenses:
77
79
  - MIT
@@ -93,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
95
  - !ruby/object:Gem::Version
94
96
  version: '0'
95
97
  requirements: []
96
- rubygems_version: 3.1.4
98
+ rubygems_version: 3.0.3
97
99
  signing_key:
98
100
  specification_version: 4
99
101
  summary: Diffable encrypted configuration files