Skip to content

Commit 20a1962

Browse files
committed
Encryptor Encryptor
1 parent 81ab235 commit 20a1962

File tree

13 files changed

+243
-40
lines changed

13 files changed

+243
-40
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
/pkg/
77
/spec/reports/
88
/tmp/
9+
Gemfile.lock

.rubocop.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
AllCops:
2+
NewCops: enable
3+
4+
Style/ClassAndModuleChildren:
5+
Exclude:
6+
- test/**/*_test.rb
7+
Style/Documentation:
8+
Enabled: false
9+
Metrics/MethodLength:
10+
Exclude:
11+
- test/**/*_test.rb
12+
13+
Layout/LineLength:
14+
Exclude:
15+
- test/**/*_test.rb

Gemfile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
source "https://rubygems.org"
1+
# frozen_string_literal: true
2+
3+
source 'https://rubygems.org'
24

35
# Specify your gem's dependencies in diffcrypt.gemspec
46
gemspec
57

6-
gem "rake", "~> 12.0"
7-
gem "minitest", "~> 5.0"
8+
gem 'minitest', '~> 5.0'
9+
gem 'rake', '~> 13.0'
10+
gem 'rubocop', '~> 0.86'

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Diffcrypt
22

3-
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/diffcrypt`. To experiment with that code, run `bin/console` for an interactive prompt.
3+
Diffable encrypted files that you can safely commit into your repo.
4+
45

5-
TODO: Delete this and the text above, and describe your gem
66

77
## Installation
88

@@ -20,21 +20,44 @@ Or install it yourself as:
2020

2121
$ gem install diffcrypt
2222

23+
24+
2325
## Usage
2426

25-
TODO: Write usage instructions here
27+
28+
### Encrypt existing file
29+
30+
```ruby
31+
encryptor = Diffcrypt::Encryptor.new('99e1f86b9e61f24c56ff4108dd415091')
32+
yaml = File.read('tmp/example.yml')
33+
encrypted = encryptor.encrypt(yaml)
34+
File.write('tmp/example.yml.enc', encrypted)
35+
```
36+
37+
### Decrypt a file
38+
39+
```ruby
40+
encryptor = Diffcrypt::Encryptor.new('99e1f86b9e61f24c56ff4108dd415091')
41+
yaml = File.read('tmp/example.yml.enc')
42+
config = YAML.safe_load(encryptor.decrypt(yaml))
43+
```
44+
45+
2646

2747
## Development
2848

2949
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.
3050

3151
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
3252

53+
54+
3355
## Contributing
3456

3557
Bug reports and pull requests are welcome on GitHub at https://github.com/marcqualie/diffcrypt.
3658

3759

60+
3861
## License
3962

4063
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

Rakefile

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
require "bundler/gem_tasks"
2-
require "rake/testtask"
1+
# frozen_string_literal: true
2+
3+
require 'bundler/gem_tasks'
4+
require 'rake/testtask'
35

46
Rake::TestTask.new(:test) do |t|
5-
t.libs << "test"
6-
t.libs << "lib"
7-
t.test_files = FileList["test/**/*_test.rb"]
7+
t.libs << 'test'
8+
t.libs << 'lib'
9+
t.test_files = FileList['test/**/*_test.rb']
810
end
911

10-
task :default => :test
12+
task default: :test

bin/console

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
23

3-
require "bundler/setup"
4-
require "diffcrypt"
4+
require 'bundler/setup'
5+
require 'diffcrypt'
56

67
# You can add fixtures and/or initialization code here to make experimenting
78
# with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "diffcrypt"
1011
# require "pry"
1112
# Pry.start
1213

13-
require "irb"
14+
require 'irb'
1415
IRB.start(__FILE__)

diffcrypt.gemspec

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
1+
# frozen_string_literal: true
2+
13
require_relative 'lib/diffcrypt/version'
24

35
Gem::Specification.new do |spec|
4-
spec.name = "diffcrypt"
6+
spec.name = 'diffcrypt'
57
spec.version = Diffcrypt::VERSION
6-
spec.authors = ["Marc Qualie"]
7-
spec.email = ["marc@marcqualie.com"]
8+
spec.authors = ['Marc Qualie']
9+
spec.email = ['marc@marcqualie.com']
810

9-
spec.summary = %q{TODO: Write a short summary, because RubyGems requires one.}
10-
spec.description = %q{TODO: Write a longer description or delete this line.}
11-
spec.homepage = "TODO: Put your gem's website or public repo URL here."
12-
spec.license = "MIT"
13-
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
11+
spec.summary = 'Diffable encrypted files'
12+
spec.description = 'Diffable encrypted files'
13+
spec.homepage = 'https://github.com/marcqualie/diffcrypt'
14+
spec.license = 'MIT'
15+
spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
1416

15-
spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
17+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
1618

17-
spec.metadata["homepage_uri"] = spec.homepage
18-
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
19-
spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
19+
spec.metadata['homepage_uri'] = spec.homepage
20+
spec.metadata['source_code_uri'] = 'https://github.com/marcqualie/diffcrypt'
21+
# spec.metadata['changelog_uri'] = "TODO: Put your gem's CHANGELOG.md URL here."
2022

2123
# Specify which files should be added to the gem when it is released.
2224
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23-
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
25+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
2426
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
2527
end
26-
spec.bindir = "exe"
27-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28-
spec.require_paths = ["lib"]
28+
spec.bindir = 'exe'
29+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30+
spec.require_paths = ['lib']
31+
32+
spec.add_runtime_dependency 'activesupport', '~> 6.0.0'
2933
end

lib/diffcrypt.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
require "diffcrypt/version"
1+
# frozen_string_literal: true
2+
3+
require 'diffcrypt/encryptor'
4+
require 'diffcrypt/version'
25

36
module Diffcrypt
47
class Error < StandardError; end
5-
# Your code goes here...
68
end

lib/diffcrypt/encryptor.rb

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# frozen_string_literal: true
2+
3+
require 'pathname'
4+
require 'tmpdir'
5+
require 'securerandom'
6+
require 'yaml'
7+
8+
require 'active_support/message_encryptor'
9+
10+
module Diffcrypt
11+
class Encryptor
12+
CIPHER = 'aes-128-gcm'
13+
14+
def self.generate_key
15+
SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER))
16+
end
17+
18+
def initialize(key)
19+
@key = key
20+
@encryptor ||= ActiveSupport::MessageEncryptor.new([key].pack('H*'), cipher: CIPHER)
21+
end
22+
23+
# @param [String] contents The raw YAML string to be encrypted
24+
def decrypt(contents)
25+
yaml = YAML.safe_load contents
26+
decrypted = decrypt_hash yaml
27+
YAML.dump decrypted
28+
end
29+
30+
# @param [Hash] data
31+
# @return [Hash]
32+
def decrypt_hash(data)
33+
data.each do |key, value|
34+
data[key] = if value.is_a?(Hash) || value.is_a?(Array)
35+
decrypt_hash(value)
36+
else
37+
decrypt_string value
38+
end
39+
end
40+
data
41+
end
42+
43+
# @param [String] contents The raw YAML string to be encrypted
44+
def encrypt(contents)
45+
yaml = YAML.safe_load contents
46+
encrypted = encrypt_values yaml
47+
YAML.dump encrypted
48+
end
49+
50+
# @param [String] value Plain text string that needs encrypting
51+
# @return [String]
52+
def encrypt_string(value)
53+
@encryptor.encrypt_and_sign value
54+
end
55+
56+
# @param [Hash] keys
57+
# @return [Hash]
58+
def encrypt_values(data)
59+
data.each do |key, value|
60+
data[key] = if value.is_a?(Hash) || value.is_a?(Array)
61+
encrypt_values(value)
62+
else
63+
encrypt_string value
64+
end
65+
end
66+
data
67+
end
68+
69+
# @param [String] value The encrypted value that needs decrypting
70+
# @return [String]
71+
def decrypt_string(value)
72+
@encryptor.decrypt_and_verify value
73+
end
74+
end
75+
end

lib/diffcrypt/version.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# frozen_string_literal: true
2+
13
module Diffcrypt
2-
VERSION = "0.1.0"
4+
VERSION = '0.1.0'
35
end

0 commit comments

Comments
 (0)