pgcrypto 0.0.1 → 0.0.2
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.
- data/CHANGES +5 -0
- data/README.markdown +19 -13
- data/VERSION +1 -1
- data/lib/pgcrypto/active_record.rb +19 -18
- data/pgcrypto.gemspec +46 -0
- metadata +3 -2
data/CHANGES
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
0.0.2
|
2
|
+
* Fixed a number of key-related bugs discovered in testing with our
|
3
|
+
second production app with encrypted columns. Also duck-typed AREL
|
4
|
+
statement types in a few places.
|
5
|
+
|
1
6
|
0.0.1
|
2
7
|
* INSERT, SELECT, and UPDATE statements are working. But I wrote this
|
3
8
|
while testing with a production app, and thus haven't written
|
data/README.markdown
CHANGED
@@ -22,9 +22,12 @@ You need to have PGCrypto installed before this guy will work. [LMGTFY](http://l
|
|
22
22
|
PGCrypto.keys[:private] = {:path => "~/.keys/private.key"}
|
23
23
|
PGCrypto.keys[:public] = {:path => "~/.keys/public.key"}
|
24
24
|
|
25
|
-
4. PGCrypto columns are named `attribute_encrypted`
|
25
|
+
4. PGCrypto columns are named `attribute_encrypted` in the binary format, so do something like this:
|
26
26
|
|
27
|
-
add_column :users, :
|
27
|
+
add_column :users, :social_security_number_encrypted, :binary
|
28
|
+
|
29
|
+
This will allow you to access `User#social_security_number` and store the user's social in an encrypted
|
30
|
+
column called `social_security_number_encryped`.
|
28
31
|
|
29
32
|
5. Tell the User class to encrypt and decrypt the `social_security_number` attribute on the fly:
|
30
33
|
|
@@ -47,14 +50,15 @@ a GPG-encrypted column that can only be decrypted with your secure key.
|
|
47
50
|
Keys
|
48
51
|
-
|
49
52
|
|
50
|
-
|
51
|
-
|
53
|
+
If you want to bundle your public key with your application, PGCrypto will automatically load `#{Rails.root}/.pgcrypto`,
|
54
|
+
so feel free to put your public key in there. You can also tell PGCrypto about your keys in a number of fun ways.
|
55
|
+
The most straightforward is to assign the actual content of the key manually:
|
52
56
|
|
53
57
|
PGCrypto.keys[:private] = "-----BEGIN PGP PRIVATE KEY BLOCK----- ..."
|
54
58
|
|
55
59
|
You can also give it more specific stuff:
|
56
60
|
|
57
|
-
PGCrypto.keys[:private] = {:path => ".private.key", :armored =>
|
61
|
+
PGCrypto.keys[:private] = {:path => ".private.key", :armored => false, :password => "myKeyPASSwhichizneededBRO"}
|
58
62
|
|
59
63
|
This is especially important if you password protect your private key files (and you SHOULD, for the record)!
|
60
64
|
|
@@ -69,8 +73,7 @@ If you do that, just tell PGCrypto which keys to use on which columns, using an
|
|
69
73
|
pgcrypto :social_security_number, :private_key => :user_private, :public_key => :user_public
|
70
74
|
end
|
71
75
|
|
72
|
-
|
73
|
-
so feel free to put your public key in there. I recommend deploy-time passing of your private key and password, to ensure it
|
76
|
+
I recommend deploy-time passing of your private key and password, to ensure it
|
74
77
|
doesn't wind up in any long-term storage on the server:
|
75
78
|
|
76
79
|
PGCrypto.keys[:private] = {:value => ENV['PRIVATE_KEY'], :password => ENV['PRIVATE_KEY_PASSWORD']}
|
@@ -78,11 +81,15 @@ doesn't wind up in any long-term storage on the server:
|
|
78
81
|
Warranty
|
79
82
|
-
|
80
83
|
|
81
|
-
As I mentioned before, this library is one HUGE hack.
|
82
|
-
|
83
|
-
|
84
|
+
As I mentioned before, this library is one HUGE hack. This is just scratching the surface of keeping your data secure.
|
85
|
+
For example, if you don't protect your log files, anyone who can read them can get your private and public keys and
|
86
|
+
decrypt whatever the hell they want. You'll also have to scrub your logs, because un-encrypted data is displayed right
|
87
|
+
alongside those private and public keys.
|
88
|
+
|
89
|
+
Basically, this will make it easy to start with asymmetric, GPG-based, column-level encryption in PostgreSQL. But that's about
|
90
|
+
it; the rest is up to you.
|
84
91
|
|
85
|
-
As such
|
92
|
+
**As such,** the author and Delightful Widgets Inc. offer ***ABSOLUTELY NO GODDAMN WARRANTY***. As I mentioned, this works great in our
|
86
93
|
Rails 3.2 world, but YMMV if your version of Arel or ActiveRecord are ahead or behind ours. Sorry, folks.
|
87
94
|
|
88
95
|
WTF NO TESTS?!!
|
@@ -91,5 +98,4 @@ WTF NO TESTS?!!
|
|
91
98
|
Nope. We built this inside of a production application, and used its test suite to debug everything. Since this is really just
|
92
99
|
a preview release, I haven't written a suite for it yet. Sorry.
|
93
100
|
|
94
|
-
|
95
|
-
Copyright (C) 2012 Delightful Widgets, Inc.
|
101
|
+
Copyright (C) 2012 Delightful Widgets, Inc. Built by Flip Sasser, Monkeypatcher Extraordinaire!
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
@@ -20,11 +20,12 @@ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
|
|
20
20
|
unless PGCrypto[table].empty?
|
21
21
|
arel.ast.columns.each_with_index do |column, i|
|
22
22
|
if options = PGCrypto[table][column.name]
|
23
|
-
key = PGCrypto.keys[options[:public_key] || :public]
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
if key = PGCrypto.keys[options[:public_key] || :public]
|
24
|
+
value = arel.ast.values.expressions[i]
|
25
|
+
quoted_value = quote_string(value)
|
26
|
+
encryption_instruction = %[pgp_pub_encrypt(#{quoted_value}, #{key.dearmored})]
|
27
|
+
arel.ast.values.expressions[i] = Arel::Nodes::SqlLiteral.new(encryption_instruction)
|
28
|
+
end
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
@@ -67,11 +68,12 @@ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
|
|
67
68
|
# Now loop through the children to encrypt them for the SELECT
|
68
69
|
where.children.each do |child|
|
69
70
|
if options = PGCrypto[child.left.relation.name]["#{child.left.name}_encrypted"]
|
70
|
-
key = PGCrypto.keys[options[:private_key] || :private]
|
71
|
-
|
72
|
-
|
71
|
+
if key = PGCrypto.keys[options[:private_key] || :private]
|
72
|
+
joins[key.name] ||= "#{key.dearmored} AS #{key.name}_key"
|
73
|
+
child.left = Arel::Nodes::SqlLiteral.new("pgp_pub_decrypt(#{child.left.name}_encrypted, keys.#{key.name}_key)")
|
74
|
+
end
|
73
75
|
end
|
74
|
-
end
|
76
|
+
end if where.respond_to?(:children)
|
75
77
|
end
|
76
78
|
end
|
77
79
|
unless joins.empty?
|
@@ -81,22 +83,21 @@ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
|
|
81
83
|
|
82
84
|
def pgcrypto_tweak_select_column(column, options, joins)
|
83
85
|
return nil unless options[:type] == :pgp
|
84
|
-
key = PGCrypto.keys[options[:private_key] || :private]
|
85
|
-
|
86
|
-
|
87
|
-
|
86
|
+
if key = PGCrypto.keys[options[:private_key] || :private]
|
87
|
+
select = %[pgp_pub_decrypt(#{column}, keys.#{key.name}_key#{", '#{key.password}'" if key.password}) AS "#{column.to_s.gsub(/_encrypted$/, '')}"]
|
88
|
+
joins[key.name] ||= "#{key.dearmored} AS #{key.name}_key"
|
89
|
+
Arel::Nodes::SqlLiteral.new(select)
|
90
|
+
end
|
88
91
|
end
|
89
92
|
|
90
93
|
def pgcrypto_tweak_update(arel)
|
91
94
|
# Loop through the assignments and make sure we take care of that whole
|
92
95
|
# NULL value thing!
|
93
96
|
arel.ast.values.each do |value|
|
94
|
-
if options = PGCrypto[value.left.relation.name][value.left.name]
|
95
|
-
|
96
|
-
when NilClass
|
97
|
+
if value.respond_to?(:left) && options = PGCrypto[value.left.relation.name][value.left.name]
|
98
|
+
if value.right.nil?
|
97
99
|
value.right = Arel::Nodes::SqlLiteral.new('NULL')
|
98
|
-
|
99
|
-
key = PGCrypto.keys[options[:public_key] || :public]
|
100
|
+
elsif key = PGCrypto.keys[options[:public_key] || :public]
|
100
101
|
quoted_right = quote_string(value.right)
|
101
102
|
encryption_instruction = %[pgp_pub_encrypt('#{quoted_right}', #{key.dearmored})]
|
102
103
|
value.right = Arel::Nodes::SqlLiteral.new(encryption_instruction)
|
data/pgcrypto.gemspec
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "pgcrypto"
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Flip Sasser"]
|
12
|
+
s.date = "2012-02-24"
|
13
|
+
s.description = "\n PGCrypto is an ActiveRecord::Base extension that allows you to asymmetrically\n encrypt PostgreSQL columns with as little trouble as possible. It's totally\n freaking rad.\n "
|
14
|
+
s.email = "flip@x451.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.markdown"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".rspec",
|
21
|
+
"CHANGES",
|
22
|
+
"LICENSE",
|
23
|
+
"README.markdown",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/pgcrypto.rb",
|
27
|
+
"lib/pgcrypto/active_record.rb",
|
28
|
+
"lib/pgcrypto/arel.rb",
|
29
|
+
"lib/pgcrypto/key.rb",
|
30
|
+
"lib/pgcrypto/table_manager.rb"
|
31
|
+
]
|
32
|
+
s.homepage = "http://github.com/Plinq/pgcrypto"
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubygems_version = "1.8.10"
|
35
|
+
s.summary = "A transparent ActiveRecord::Base extension for encrypted columns"
|
36
|
+
|
37
|
+
if s.respond_to? :specification_version then
|
38
|
+
s.specification_version = 3
|
39
|
+
|
40
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
41
|
+
else
|
42
|
+
end
|
43
|
+
else
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pgcrypto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-28 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! "\n PGCrypto is an ActiveRecord::Base extension that allows you
|
15
15
|
to asymmetrically\n encrypt PostgreSQL columns with as little trouble as possible.
|
@@ -32,6 +32,7 @@ files:
|
|
32
32
|
- lib/pgcrypto/arel.rb
|
33
33
|
- lib/pgcrypto/key.rb
|
34
34
|
- lib/pgcrypto/table_manager.rb
|
35
|
+
- pgcrypto.gemspec
|
35
36
|
homepage: http://github.com/Plinq/pgcrypto
|
36
37
|
licenses: []
|
37
38
|
post_install_message:
|