ejson 0.2.2 → 0.3.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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +14 -7
- data/ejson.gemspec +2 -1
- data/lib/ejson.rb +2 -2
- data/lib/ejson/cli.rb +9 -1
- data/lib/ejson/encryption.rb +11 -10
- data/lib/ejson/version.rb +2 -2
- data/test/ejson_test.rb +30 -3
- metadata +17 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e7a3d4927ceae8e72ece8df8749391e2620d683
|
4
|
+
data.tar.gz: d3f5c4b1c24e2d73cde70f136f3a64c6ed0abb18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8925b554189010a94fe8760c184c92ab3ab72771ef3cd217192f9a04067f4a650e086d3d3e9ed77c83e21f20ceb34fc63ef52d05965982e747706e3c72c7f490
|
7
|
+
data.tar.gz: 7b14d361b4e9b0398208205de262d9c360aeb82a6828e8e324ec0322258b18a2a3cb1a05544425c70d13f758c5ac421f2e3f6561e5903b95615efbc19339b391
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -24,13 +24,21 @@ It can be arbitrarily nested.
|
|
24
24
|
This updates `config/secrets.ejson` in place, encrypting any newly-added or
|
25
25
|
modified values that are not yet encrypted. `ejson` is short-hand for `ejson encrypt`.
|
26
26
|
|
27
|
+
By default, it uses a public key that you won't be able to decrypt (and
|
28
|
+
shouldn't use because we *can* decrypt it!). You can use your own by following
|
29
|
+
the "Custom keypair" directions below. Feel free to fork the gem to reference
|
30
|
+
your own keypair by default.
|
31
|
+
|
27
32
|
#### 3) Decrypt the file:
|
28
33
|
|
29
34
|
ejson decrypt -k ~/.keys/ejson.priv.pem -p config/ejson.pub.pem secrets.production.ejson > secrets.production.json
|
35
|
+
# OR
|
36
|
+
ejson decrypt -i -k ~/.keys/ejson.priv.pem -p config/ejson.pub.pem secrets.production.ejson
|
30
37
|
|
31
38
|
Unlike encrypt, decrypt doesn't update the file in-place; it prints the
|
32
39
|
decrypted contents to stdout. It also requires access to the private key
|
33
|
-
created in step 1.
|
40
|
+
created in step 1. By default, the secrets will be decrypted to stdout,
|
41
|
+
but passing the `-i` flag causes them to be overwritten to the input file.
|
34
42
|
|
35
43
|
#### See `ejson help` for more information.
|
36
44
|
|
@@ -39,16 +47,15 @@ created in step 1.
|
|
39
47
|
We use a single keypair internally; the default public key is fetched from S3
|
40
48
|
on each run. However, you can generate your own keypair like so:
|
41
49
|
|
42
|
-
mkdir config && cd config
|
43
50
|
openssl req -x509 -nodes -days 100000 -newkey rsa:2048 -keyout privatekey.pem -out publickey.pem -subj '/'
|
44
51
|
|
45
52
|
`publickey.pem` and `privatekey.pem` are created. Move `privatekey.pem`
|
46
|
-
somewhere more
|
47
|
-
|
48
|
-
mkdir -p ~/.keys
|
49
|
-
mv config/privatekey.pem ~/.keys/ejson.pem
|
53
|
+
somewhere more private, and move `publickey.pem` somewhere more public.
|
50
54
|
|
51
55
|
Then you can encrypt like:
|
52
56
|
|
53
|
-
ejson encrypt -p
|
57
|
+
ejson encrypt -p publickey.pem secrets.ejson
|
58
|
+
|
59
|
+
If you'd like to fork the gem to reference your own public key, that
|
60
|
+
information lives around line 10 of `lib/ejson/cli.rb`.
|
54
61
|
|
data/ejson.gemspec
CHANGED
@@ -5,7 +5,7 @@ require 'ejson/version'
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "ejson"
|
8
|
-
spec.version =
|
8
|
+
spec.version = EJSON::VERSION
|
9
9
|
spec.authors = ["Burke Libbey"]
|
10
10
|
spec.email = ["burke.libbey@shopify.com"]
|
11
11
|
spec.summary = %q{Asymmetric keywise encryption for JSON}
|
@@ -19,4 +19,5 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_runtime_dependency "thor", "~> 0.18"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.3.2"
|
22
23
|
end
|
data/lib/ejson.rb
CHANGED
@@ -6,8 +6,8 @@ class EJSON
|
|
6
6
|
extend Forwardable
|
7
7
|
def_delegators :@encryption, :load_string, :dump_string
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
@encryption = Encryption.new(
|
9
|
+
def initialize(public_key, private_key = nil)
|
10
|
+
@encryption = Encryption.new(public_key, private_key)
|
11
11
|
end
|
12
12
|
|
13
13
|
def load(json_text)
|
data/lib/ejson/cli.rb
CHANGED
@@ -12,10 +12,17 @@ class EJSON
|
|
12
12
|
default_task :encrypt
|
13
13
|
|
14
14
|
desc "decrypt [file]", "decrypt some data from file to stdout"
|
15
|
+
method_option :inplace, type: :boolean, default: false, aliases: "-i", desc: "Overwrite input file rather than dumping to stdout"
|
15
16
|
def decrypt(file)
|
16
17
|
ciphertext = File.read(file)
|
17
18
|
ej = EJSON.new(pubkey, options[:privkey])
|
18
|
-
|
19
|
+
output = JSON.pretty_generate(ej.load(ciphertext).decrypt_all)
|
20
|
+
if options[:inplace]
|
21
|
+
File.open(file, "w") { |f| f.puts output }
|
22
|
+
puts "Wrote #{output.size} bytes to #{file}"
|
23
|
+
else
|
24
|
+
puts output
|
25
|
+
end
|
19
26
|
rescue EJSON::Encryption::PrivateKeyMissing => e
|
20
27
|
fatal("can't decrypt data without private key (specify path with -k)", e)
|
21
28
|
rescue EJSON::Encryption::ExpectedEncryptedString => e
|
@@ -41,6 +48,7 @@ class EJSON
|
|
41
48
|
|
42
49
|
desc "version", "show version information"
|
43
50
|
def version
|
51
|
+
require 'ejson/version'
|
44
52
|
puts "ejson version #{EJSON::VERSION}"
|
45
53
|
end
|
46
54
|
|
data/lib/ejson/encryption.rb
CHANGED
@@ -7,10 +7,10 @@ class EJSON
|
|
7
7
|
PrivateKeyMissing = Class.new(StandardError)
|
8
8
|
ExpectedEncryptedString = Class.new(StandardError)
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
@public_key_x509 = load_public_key(
|
12
|
-
if
|
13
|
-
@private_key_rsa = load_private_key(
|
10
|
+
def initialize(public_key, private_key)
|
11
|
+
@public_key_x509 = load_public_key(public_key)
|
12
|
+
if private_key
|
13
|
+
@private_key_rsa = load_private_key(private_key)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -47,15 +47,16 @@ class EJSON
|
|
47
47
|
pkcs7.decrypt(@private_key_rsa, @public_key_x509)
|
48
48
|
end
|
49
49
|
|
50
|
-
def load_public_key(
|
51
|
-
|
52
|
-
OpenSSL::X509::Certificate.new(public_key_pem)
|
50
|
+
def load_public_key(public_key)
|
51
|
+
OpenSSL::X509::Certificate.new(get_pem(public_key))
|
53
52
|
end
|
54
53
|
|
55
|
-
def load_private_key(
|
56
|
-
|
57
|
-
OpenSSL::PKey::RSA.new(private_key_pem)
|
54
|
+
def load_private_key(private_key)
|
55
|
+
OpenSSL::PKey::RSA.new(get_pem(private_key))
|
58
56
|
end
|
59
57
|
|
58
|
+
def get_pem(string)
|
59
|
+
string =~ /^-----BEGIN/ ? string : File.read(string)
|
60
|
+
end
|
60
61
|
end
|
61
62
|
end
|
data/lib/ejson/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
class
|
2
|
-
VERSION = "0.
|
1
|
+
class EJSON
|
2
|
+
VERSION = "0.3.0"
|
3
3
|
end
|
data/test/ejson_test.rb
CHANGED
@@ -6,7 +6,7 @@ require 'ejson/cli'
|
|
6
6
|
class CLITest < Minitest::Unit::TestCase
|
7
7
|
|
8
8
|
def test_ejson
|
9
|
-
f = Tempfile.
|
9
|
+
f = Tempfile.new("encrypt")
|
10
10
|
|
11
11
|
f.puts JSON.dump({a: "b"})
|
12
12
|
f.close
|
@@ -33,8 +33,25 @@ class CLITest < Minitest::Unit::TestCase
|
|
33
33
|
File.unlink(f.path)
|
34
34
|
end
|
35
35
|
|
36
|
+
def test_inplace
|
37
|
+
f = Tempfile.new("encrypt")
|
38
|
+
|
39
|
+
f.puts JSON.dump({a: "b"})
|
40
|
+
f.close
|
41
|
+
|
42
|
+
runcli "encrypt", "-p", pubkey, f.path
|
43
|
+
encrypted = JSON.load(File.read(f.path))
|
44
|
+
assert_match(/\AENC\[MIIB.*\]\z/, encrypted["a"])
|
45
|
+
|
46
|
+
runcli "decrypt", "-i", "-p", pubkey, "-k", privkey, f.path
|
47
|
+
decrypted = JSON.load(File.read(f.path))
|
48
|
+
refute_match(/\AENC\[MIIB.*\]\z/, decrypted["a"])
|
49
|
+
ensure
|
50
|
+
File.unlink(f.path)
|
51
|
+
end
|
52
|
+
|
36
53
|
def test_default_key_exists
|
37
|
-
f = Tempfile.
|
54
|
+
f = Tempfile.new("encrypt")
|
38
55
|
|
39
56
|
f.puts JSON.dump({a: "b"})
|
40
57
|
f.close
|
@@ -50,7 +67,7 @@ class CLITest < Minitest::Unit::TestCase
|
|
50
67
|
end
|
51
68
|
|
52
69
|
def test_library_is_picky
|
53
|
-
f = Tempfile.
|
70
|
+
f = Tempfile.new("decrypt")
|
54
71
|
f.puts JSON.dump({a: "b"})
|
55
72
|
f.close
|
56
73
|
assert_raises(EJSON::Encryption::ExpectedEncryptedString) {
|
@@ -60,6 +77,16 @@ class CLITest < Minitest::Unit::TestCase
|
|
60
77
|
File.unlink(f.path)
|
61
78
|
end
|
62
79
|
|
80
|
+
def test_key_strings
|
81
|
+
public_key = File.read(pubkey)
|
82
|
+
private_key = File.read(privkey)
|
83
|
+
|
84
|
+
@enc = EJSON::Encryption.new(public_key, private_key)
|
85
|
+
|
86
|
+
assert_equal public_key, @enc.instance_variable_get(:@public_key_x509).to_s
|
87
|
+
assert_equal private_key, @enc.instance_variable_get(:@private_key_rsa).to_s
|
88
|
+
end
|
89
|
+
|
63
90
|
private
|
64
91
|
|
65
92
|
def encrypt(path)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ejson
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Burke Libbey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.18'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 10.3.2
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 10.3.2
|
27
41
|
description: Secret management by encrypting values in a JSON hash with a public/private
|
28
42
|
keypair
|
29
43
|
email:
|
@@ -67,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
81
|
version: '0'
|
68
82
|
requirements: []
|
69
83
|
rubyforge_project:
|
70
|
-
rubygems_version: 2.2.
|
84
|
+
rubygems_version: 2.2.2
|
71
85
|
signing_key:
|
72
86
|
specification_version: 4
|
73
87
|
summary: Asymmetric keywise encryption for JSON
|
@@ -75,4 +89,3 @@ test_files:
|
|
75
89
|
- test/ejson_test.rb
|
76
90
|
- test/privatekey.pem
|
77
91
|
- test/publickey.pem
|
78
|
-
has_rdoc:
|