encrypted_json 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in encrypted_json.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Matt Jezorek
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # EncryptedJson
2
+
3
+ This is a library to do encryption of JSON
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'encrypted_json'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install encrypted_json
18
+
19
+ ## Usage
20
+
21
+
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ desc "Run all tests"
5
+ task :default => :spec
6
+
7
+ desc "Run Specs"
8
+ task :spec do
9
+ system 'bundle exec rspec --color --format documentation spec/*_spec.rb'
10
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'encrypted_json/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "encrypted_json"
8
+ spec.version = EncryptedJson::VERSION
9
+ spec.authors = ["Matt Jezorek"]
10
+ spec.email = ["mjezorek@gmail.com"]
11
+ spec.description = %q{This gem will enable you to sign and encrypt JSON for webservice calls or other reasons with public/private keys}
12
+ spec.summary = %q{Public/Private key encryption and signing of JSON}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "json"
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec"
25
+ end
@@ -0,0 +1,77 @@
1
+ require "json"
2
+ require "base64"
3
+ require "encrypted_json/version"
4
+ require "encrypted_json/errors"
5
+ require 'openssl' unless defined?(OpenSSL)
6
+
7
+ module EncryptedJson
8
+ class Secure
9
+
10
+ def initialize(key, password='', digest='SHA1')
11
+ if password != ''
12
+ @key = OpenSSL::PKey::RSA.new(key, password)
13
+ else
14
+ @key = OpenSSL::PKey::RSA.new(key)
15
+ end
16
+ @digest = digest
17
+ end
18
+
19
+ def encrypt(input, password = '')
20
+ if input.is_a?(String)
21
+ i = input
22
+ else
23
+ i = input.to_json
24
+ end
25
+ begin
26
+ if @key.private?
27
+ data = Base64.encode64(@key.private_encrypt(i))
28
+ else
29
+ data = Base64.encode64(@key.public_encrypt(i))
30
+ end
31
+ [sign(i), data].to_json
32
+ rescue => e
33
+ raise EncryptionError
34
+ end
35
+ end
36
+
37
+ def decrypt(input, password = '')
38
+ data = ""
39
+ digest, edata = json_decode(input)
40
+ begin
41
+ if @key.private?
42
+ data = @key.private_decrypt(Base64.decode64(edata))
43
+ else
44
+ data = @key.public_decrypt(Base64.decode64(edata))
45
+ end
46
+ rescue => e
47
+ raise DecryptionError
48
+ end
49
+ raise SignatureError unless digest == sign(data)
50
+ begin
51
+ JSON.parse(data)
52
+ rescue
53
+ data
54
+ end
55
+ end
56
+
57
+ def json_decode(input)
58
+ begin
59
+ parts = JSON.parse(input)
60
+ rescue TypeError, JSON::ParserError
61
+ raise InputError
62
+ end
63
+ raise InputError unless parts.instance_of?(Array) && parts.length == 2
64
+ parts
65
+ end
66
+
67
+ def sign(input)
68
+ digest = OpenSSL::Digest.const_get(@digest).new
69
+ if @key.private?
70
+ secret = Digest::MD5.hexdigest(@key.public_key.to_der)
71
+ else
72
+ secret = Digest::MD5.hexdigest(@key.to_der)
73
+ end
74
+ OpenSSL::HMAC.hexdigest(digest, secret, input)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,7 @@
1
+ module EncryptedJson
2
+ class Error < RuntimeError; end
3
+ class InputError < Error; end
4
+ class SignatureError < Error; end
5
+ class EncryptionError < Error; end
6
+ class DecryptionError < Error; end
7
+ end
@@ -0,0 +1,3 @@
1
+ module EncryptedJson
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe EncryptedJson do
4
+ describe "round trip private encryption/decryption" do
5
+ it 'round trip as string' do
6
+ "a string".should round_trip_private_encrypted_json
7
+ end
8
+
9
+ it "round-trips an array of strings and ints" do
10
+ [1, 'a', 2, 'b'].should round_trip_private_encrypted_json
11
+ end
12
+
13
+ it "round-trips a hash with string keys, string and int values" do
14
+ { 'a' => 'b', 'b' => 2 }.should round_trip_private_encrypted_json
15
+ end
16
+
17
+ it "round-trips a nested array" do
18
+ [ 'a', [ 'b', [ 'c', 'd' ], 'e' ], 'f' ].should round_trip_private_encrypted_json
19
+ end
20
+
21
+ it "round-trips a hash/array/string/int structure" do
22
+ { 'a' => [ 'b' ], 'd' => { 'e' => 'f' }, 'g' => 10 }.should round_trip_private_encrypted_json
23
+ end
24
+ end
25
+
26
+
27
+
28
+ describe "round trip public encryption/decryption" do
29
+ it 'round trip as string' do
30
+ "a string".should round_trip_public_encrypted_json
31
+ end
32
+
33
+ it "round-trips an array of strings and ints" do
34
+ [1, 'a', 2, 'b'].should round_trip_public_encrypted_json
35
+ end
36
+
37
+ it "round-trips a hash with string keys, string and int values" do
38
+ { 'a' => 'b', 'b' => 2 }.should round_trip_public_encrypted_json
39
+ end
40
+
41
+ it "round-trips a nested array" do
42
+ [ 'a', [ 'b', [ 'c', 'd' ], 'e' ], 'f' ].should round_trip_public_encrypted_json
43
+ end
44
+
45
+ it "round-trips a hash/array/string/int structure" do
46
+ { 'a' => [ 'b' ], 'd' => { 'e' => 'f' }, 'g' => 10 }.should round_trip_public_encrypted_json
47
+ end
48
+ end
49
+
50
+ describe "Secure#encrypt" do
51
+
52
+ it "returns a string" do
53
+ encrypter = EncryptedJson::Secure.new(File.read("spec/private.pem"), 'abcd').encrypt('test')
54
+ encrypter.should be_instance_of(String)
55
+ end
56
+
57
+ it "returns a valid JSON-encoded array" do
58
+ encrypter = EncryptedJson::Secure.new(File.read("spec/private.pem"), 'abcd').encrypt('test')
59
+ JSON.parse(encrypter).should be_instance_of(Array)
60
+ end
61
+ end
62
+
63
+ end
data/spec/private.pem ADDED
@@ -0,0 +1,31 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ Proc-Type: 4,ENCRYPTED
3
+ DEK-Info: DES-EDE3-CBC,0CE99AF26B7E280D
4
+
5
+ QMbKZtEolKHd6GS/VhWT7JpO+Ux2yZI54+OPVhPQ6K7/IjOM+CTAuWIn4H8/Xt7z
6
+ Nl0p6ZHs2M2GILPiWVNCgkh0yhjEbNcFTX9f7I82E1KvdoV2GrBf4nzvuqxy/NAY
7
+ pq/xc5kWbbKwcEFCoIQjhYXORmn5Msi3AbSRSfmLatEPnVT0uOO8sI7aryXJ3e+B
8
+ c794RFS56JrQKbgPUUo1jz4dPnp7WF5FCEdfpyBvNZCy2QNji23hMGTc3msAWYuB
9
+ bsBxISiK9MRjDYDqkkSKEdzDp2VID5dPKdGjwK5VebUWkR/gJiaD1dG0fTLuL0nL
10
+ yOzLGWAss1TkUKJ4gOZfCfA2jkjgG9mokANtPav5FOqhBcpwWOp9ZbYIMKBzfEos
11
+ 4me29uBgTtQPGRJ/I8s8bG95aHx0Yb48cXQutzGthlO0DD+QwCW1YeKFghDMHefm
12
+ 84iFANDaSX8IBGMuacBB1+4B9DGzDZ8NM9UiK7hqIIpiXpkX9UtfxTg2LedcZM24
13
+ PP6g7mhJ27EA5MOL+eGIA8xZY/UebJXR4w2DYZmqHZjCIsWSaNkDaXreuMzteIbX
14
+ nrb3Kd7JmI0m9ngtXzG4pjwwLOYf2XpEFvwMDPI+k16JgwcaCmSWsFhldLRBZAQL
15
+ ySV9IW5YUfKzFsCsWd6jrifaNlp36bbuvE650ifQrWP5qzUnYEM2zny+RaR+FKh2
16
+ 9wFo3BWgJLT82oEaWFfaddTGbRRGD5kxFF/m2je2CBQBVNMdP3qQqredMqDvPITO
17
+ EWpv0O8LN9vaR0lyZpitEdaFeTcc2djwAQggbmg2cJxrQtLgL2GizUTuLDHAeZgW
18
+ zUtgxu51piRkkH5KeNy+EIhD3ZaZRklR6+MkEafMVioIjTBrS2U5E7jsQBLMMY7g
19
+ 7wfw8D2LpucUPdnAD7MyQKSNgKm3krE9vEYUlz5dWO5FLo449VDiBN/FlwybcjH6
20
+ 8RCA5mx2T1vhPItINuEv2XhCANrbHy8x7HALnf9DRW5F09I7E4XQAaWvLUbJ+pOE
21
+ 6jpX2clvrvsL/yELx+hcHyf2Q++lTEcbE3jHhq8EFjPQNlrQ3DoUugq7a5I3AvSV
22
+ QPrI/RBgEXBgn/5sztpc921J4cY9Xt4c3Sjh0lzSlCK7t2QemJVp3LlinjGX7wXu
23
+ xT/py375kdS6GWU2HpSnjttgm2UwIMkKuv7JioJzpnkZ+O0gTa608AnKBmksnKS7
24
+ owiK4ALGgnIeSDJX5q6g7lC3SNKl7EgR3ijN/z/ZgGJQiwJXBY7C6UIbcNW2+mxd
25
+ GhW4nl/sCbaNVZpbFRoa6d4DdPp/qujit7Gz3azBeUhbcHbK/ruJDewF2YMqWtqe
26
+ PTTKrUcFSBHSLsnrUHZ9afH1ALNG6NviQYknrT8ldrUI6E8WUy1OSdT9a6R97l0x
27
+ vPmVyMeREKtEfL+qVp6PMFm0V8qMocXUYDjFQEPkKWK71ZencluwaFwpJfzwKqIF
28
+ iOug7coJbPpkeNkHlyxFncZTaiN6SG7M2caMrVIfb+RzqyIo0cMx9sjMM1C9u4Pi
29
+ VCccUVGQxETvczCHubY798hkBrZ+g8O1aZq+oNQjbs5lhhD5PPP+/9tZ15QtldSr
30
+ VC9UZnXCnWhQxrCrcpVz2A==
31
+ -----END RSA PRIVATE KEY-----
data/spec/public.pem ADDED
@@ -0,0 +1,9 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIIBJjANBgkqhkiG9w0BAQEFAAOCARMAMIIBDgKCAQUNEbFpS+zLc30lOkbLBFG7
3
+ mcgCZPXSMPnRLogU2LZLePkWur7HskdannVEr6k7pbsirflehU01EYdTm/WNfJuV
4
+ 01jAyfkLr9AQZ7XpllUsWv9V0+0I5jMVDPZx/2cr8zELs4ILlhz9VH4OY9PfdEWo
5
+ XVi7o0VTSJFsipW7d7SebxqtQ6AiWtwEyRPQ48wybxuQfshaoDwdyAdjkcVF1Md0
6
+ IHs+UtShQP4Hqmg7XOZItJ0EPEuvPY0muO2CDjf8yIV7eisF4TZXMNaeiIVjOgpN
7
+ 8SP/SwRtAYmqTxrt1qNL/rWB1h3LYXZEP19U+ytRAL5YUjyKirYc0K/gJz82IF/F
8
+ knx1mykCAwEAAQ==
9
+ -----END PUBLIC KEY-----
@@ -0,0 +1,62 @@
1
+ require "encrypted_json"
2
+ RSpec::Matchers.define :round_trip_private_encrypted_json do
3
+ match do | actual |
4
+ encrypter = EncryptedJson::Secure.new(File.read("spec/private.pem"), 'abcd')
5
+ decrypter = EncryptedJson::Secure.new(File.read("spec/public.pem"))
6
+
7
+ @encoded = encrypter.encrypt(actual)
8
+ @decoded = decrypter.decrypt(@encoded)
9
+
10
+ if @encoded == actual
11
+ fail_because :not_encrypted
12
+ elsif @decoded != actual
13
+ fail_because :mismatch
14
+ else
15
+ true
16
+ end
17
+ end
18
+
19
+ def fail_because(reason_code)
20
+ @reason = reason_code
21
+ false
22
+ end
23
+
24
+ failure_message_for_should do | actual |
25
+ if @reason == :not_encrypted
26
+ "Expected encrypted to be different to original input: #{actual}"
27
+ elsif @reason == :mismatch
28
+ "Expected decdoe to equal original input, got '#{@decoded}'"
29
+ end
30
+ end
31
+ end
32
+
33
+ RSpec::Matchers.define :round_trip_public_encrypted_json do
34
+ match do | actual |
35
+ encrypter = EncryptedJson::Secure.new(File.read("spec/public.pem"))
36
+ decrypter = EncryptedJson::Secure.new(File.read("spec/private.pem"), 'abcd')
37
+
38
+ @encoded = encrypter.encrypt(actual)
39
+ @decoded = decrypter.decrypt(@encoded)
40
+
41
+ if @encoded == actual
42
+ fail_because :not_encrypted
43
+ elsif @decoded != actual
44
+ fail_because :mismatch
45
+ else
46
+ true
47
+ end
48
+ end
49
+
50
+ def fail_because(reason_code)
51
+ @reason = reason_code
52
+ false
53
+ end
54
+
55
+ failure_message_for_should do | actual |
56
+ if @reason == :not_encrypted
57
+ "Expected encrypted to be different to original input: #{actual}"
58
+ elsif @reason == :mismatch
59
+ "Expected decdoe to equal original input, got '#{@decoded}'"
60
+ end
61
+ end
62
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: encrypted_json
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Matt Jezorek
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2013-09-30 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: json
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: bundler
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 1
41
+ - 3
42
+ version: "1.3"
43
+ type: :development
44
+ version_requirements: *id002
45
+ - !ruby/object:Gem::Dependency
46
+ name: rake
47
+ prerelease: false
48
+ requirement: &id003 !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ type: :development
56
+ version_requirements: *id003
57
+ - !ruby/object:Gem::Dependency
58
+ name: rspec
59
+ prerelease: false
60
+ requirement: &id004 !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ type: :development
68
+ version_requirements: *id004
69
+ description: This gem will enable you to sign and encrypt JSON for webservice calls or other reasons with public/private keys
70
+ email:
71
+ - mjezorek@gmail.com
72
+ executables: []
73
+
74
+ extensions: []
75
+
76
+ extra_rdoc_files: []
77
+
78
+ files:
79
+ - .gitignore
80
+ - Gemfile
81
+ - LICENSE.txt
82
+ - README.md
83
+ - Rakefile
84
+ - encrypted_json.gemspec
85
+ - lib/encrypted_json.rb
86
+ - lib/encrypted_json/errors.rb
87
+ - lib/encrypted_json/version.rb
88
+ - spec/encrypted_json_spec.rb
89
+ - spec/private.pem
90
+ - spec/public.pem
91
+ - spec/spec_helper.rb
92
+ has_rdoc: true
93
+ homepage: ""
94
+ licenses:
95
+ - MIT
96
+ post_install_message:
97
+ rdoc_options: []
98
+
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ requirements: []
116
+
117
+ rubyforge_project:
118
+ rubygems_version: 1.3.6
119
+ signing_key:
120
+ specification_version: 3
121
+ summary: Public/Private key encryption and signing of JSON
122
+ test_files:
123
+ - spec/encrypted_json_spec.rb
124
+ - spec/private.pem
125
+ - spec/public.pem
126
+ - spec/spec_helper.rb