carapace 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +13 -0
- data/LICENSE +24 -0
- data/LICENSE_JSBN +40 -0
- data/README.md +96 -0
- data/Rakefile +8 -0
- data/lib/carapace.rb +124 -0
- data/rails_generators/USAGE +7 -0
- data/rails_generators/carapace_generator.rb +7 -0
- data/rails_generators/templates/carapace.js +848 -0
- data/test/rails_app/README.md +130 -0
- data/test/rails_app/Rakefile +10 -0
- data/test/rails_app/app/controllers/application.rb +10 -0
- data/test/rails_app/app/controllers/message_controller.rb +13 -0
- data/test/rails_app/app/helpers/application_helper.rb +3 -0
- data/test/rails_app/app/helpers/message_helper.rb +2 -0
- data/test/rails_app/app/views/message/index.html.erb +24 -0
- data/test/rails_app/config/boot.rb +109 -0
- data/test/rails_app/config/database.yml +19 -0
- data/test/rails_app/config/environment.rb +60 -0
- data/test/rails_app/config/environments/development.rb +18 -0
- data/test/rails_app/config/environments/production.rb +19 -0
- data/test/rails_app/config/environments/test.rb +22 -0
- data/test/rails_app/config/initializers/inflections.rb +10 -0
- data/test/rails_app/config/initializers/mime_types.rb +5 -0
- data/test/rails_app/config/routes.rb +35 -0
- data/test/rails_app/doc/README_FOR_APP +2 -0
- data/test/rails_app/log/development.log +162 -0
- data/test/rails_app/log/production.log +0 -0
- data/test/rails_app/log/server.log +0 -0
- data/test/rails_app/log/test.log +24 -0
- data/test/rails_app/public/404.html +30 -0
- data/test/rails_app/public/422.html +30 -0
- data/test/rails_app/public/500.html +30 -0
- data/test/rails_app/public/dispatch.cgi +10 -0
- data/test/rails_app/public/dispatch.fcgi +24 -0
- data/test/rails_app/public/dispatch.rb +10 -0
- data/test/rails_app/public/favicon.ico +0 -0
- data/test/rails_app/public/images/rails.png +0 -0
- data/test/rails_app/public/javascripts/application.js +2 -0
- data/test/rails_app/public/javascripts/carapace.js +844 -0
- data/test/rails_app/public/javascripts/controls.js +963 -0
- data/test/rails_app/public/javascripts/dragdrop.js +972 -0
- data/test/rails_app/public/javascripts/effects.js +1120 -0
- data/test/rails_app/public/javascripts/prototype.js +4225 -0
- data/test/rails_app/public/robots.txt +5 -0
- data/test/rails_app/script/about +3 -0
- data/test/rails_app/script/console +3 -0
- data/test/rails_app/script/destroy +3 -0
- data/test/rails_app/script/generate +3 -0
- data/test/rails_app/script/performance/benchmarker +3 -0
- data/test/rails_app/script/performance/profiler +3 -0
- data/test/rails_app/script/performance/request +3 -0
- data/test/rails_app/script/plugin +3 -0
- data/test/rails_app/script/process/inspector +3 -0
- data/test/rails_app/script/process/reaper +3 -0
- data/test/rails_app/script/process/spawner +3 -0
- data/test/rails_app/script/runner +3 -0
- data/test/rails_app/script/server +3 -0
- data/test/rails_app/test/functional/message_controller_test.rb +11 -0
- data/test/rails_app/test/test_helper.rb +38 -0
- metadata +127 -0
data/CHANGELOG.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Carapace Changelog
|
2
|
+
|
3
|
+
## 0.1.0: Wednesday 30th May 2012
|
4
|
+
|
5
|
+
Initial gem version
|
6
|
+
|
7
|
+
Written and tested against Ruby 1.8.6 and Rails 2.0.2
|
8
|
+
|
9
|
+
## Origin
|
10
|
+
|
11
|
+
The original Carapace code was written on 10th August 2007 for Ruby 1.8.6 and Rails 2.0.2.
|
12
|
+
|
13
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Copyright (c) 2007, 2012 John Lane
|
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.
|
23
|
+
|
24
|
+
http://www.opensource.org/licenses/mit-license.php
|
data/LICENSE_JSBN
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
Licensing
|
2
|
+
---------
|
3
|
+
|
4
|
+
This software is covered under the following copyright:
|
5
|
+
|
6
|
+
/*
|
7
|
+
* Copyright (c) 2003-2005 Tom Wu
|
8
|
+
* All Rights Reserved.
|
9
|
+
*
|
10
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
11
|
+
* a copy of this software and associated documentation files (the
|
12
|
+
* "Software"), to deal in the Software without restriction, including
|
13
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
14
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
15
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
16
|
+
* the following conditions:
|
17
|
+
*
|
18
|
+
* The above copyright notice and this permission notice shall be
|
19
|
+
* included in all copies or substantial portions of the Software.
|
20
|
+
*
|
21
|
+
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
22
|
+
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
23
|
+
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
24
|
+
*
|
25
|
+
* IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
|
26
|
+
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
|
27
|
+
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
|
28
|
+
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
|
29
|
+
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
30
|
+
*
|
31
|
+
* In addition, the following condition applies:
|
32
|
+
*
|
33
|
+
* All redistributions must retain an intact copy of this copyright notice
|
34
|
+
* and disclaimer.
|
35
|
+
*/
|
36
|
+
|
37
|
+
Address all questions regarding this license to:
|
38
|
+
|
39
|
+
Tom Wu
|
40
|
+
tjw@cs.Stanford.EDU
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# Carapace
|
2
|
+
|
3
|
+
Carapace enables encrypted transfer of HTTP form field values from
|
4
|
+
the view (client) to the controller (server).
|
5
|
+
|
6
|
+
The data is encrypted by the browser before being posted to the server. The
|
7
|
+
server decrypts the data ready for processing.
|
8
|
+
|
9
|
+
Example uses are transfer of user passwords or credit card numbers.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Install it:
|
14
|
+
|
15
|
+
$ gem install carapace
|
16
|
+
|
17
|
+
Configure your rails 2.x application:
|
18
|
+
|
19
|
+
$ script/generate carapace
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Client-side, Carapace uses Javascript to perform encryption. Include this like so:
|
24
|
+
|
25
|
+
<%= javascript_include_tag 'carapace.js' %>
|
26
|
+
<%= carapace_javascript %>
|
27
|
+
|
28
|
+
Use the `carapace_encrypt` Javascript function on any form fields that
|
29
|
+
require encryption. For example:
|
30
|
+
|
31
|
+
function onSubmit()
|
32
|
+
{
|
33
|
+
carapace_encrypt(document.getElementById("user_password"));
|
34
|
+
}
|
35
|
+
|
36
|
+
Then, configure the form's "submit" button to call it:
|
37
|
+
|
38
|
+
<%= submit_tag "Add User", :class => "submit", :onclick => "onSubmit()" %>
|
39
|
+
|
40
|
+
On the server, mix Carapace into a Rails controller (ApplicationController) class:
|
41
|
+
|
42
|
+
require 'carapace'
|
43
|
+
include Carapace
|
44
|
+
|
45
|
+
Then use Carapace from within action methods:
|
46
|
+
|
47
|
+
def index
|
48
|
+
carapace_session
|
49
|
+
if request.post?
|
50
|
+
@message=params[:message]
|
51
|
+
carapace_decrypt! @message
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
**Warning:** if the controller rejects a post operation and re-displays itself
|
56
|
+
the data is not encrypted when sent to the browser. To maintain security,
|
57
|
+
such fields should be cleared before rendering the view.
|
58
|
+
|
59
|
+
## Testing
|
60
|
+
|
61
|
+
Test the gem with `rake test`. There is also a self-contained rails application
|
62
|
+
in `test\rails_app` for further testing and education. See `test\rails_app\README.md`
|
63
|
+
for more information.
|
64
|
+
|
65
|
+
## History
|
66
|
+
|
67
|
+
Carapace was originally written as part of a larger application in 2007 that needed
|
68
|
+
to provide a degree of security for sensitive data in situations where SSL could
|
69
|
+
not be used.
|
70
|
+
|
71
|
+
The Carapace gem was created in 2012 to make it straightforward to re-use the
|
72
|
+
original code in new applications. This was done primarily as a learning exercise.
|
73
|
+
|
74
|
+
For revision history see CHANGELOG.md
|
75
|
+
|
76
|
+
## Acknowledgement
|
77
|
+
|
78
|
+
Carapace makes use of the [JSBN Library by Tom Wu](http://www-cs-students.stanford.edu/~tjw/jsbn/)
|
79
|
+
under the terms of its license (see file LICENCE\_JSBN).
|
80
|
+
|
81
|
+
## About the Name
|
82
|
+
|
83
|
+
A _Carapace_ is the protective shell that covers and protects animals
|
84
|
+
such as crabs and turtles.
|
85
|
+
|
86
|
+
Definitions:
|
87
|
+
[Oxford](http://oxforddictionaries.com/definition/carapace?q=carapace)
|
88
|
+
[Cambridge](http://dictionary.cambridge.org/dictionary/british/carapace)
|
89
|
+
|
90
|
+
In a similar vein, this gem allows a protective shell to surround data sent from
|
91
|
+
a browser to a web server.
|
92
|
+
|
93
|
+
## License
|
94
|
+
|
95
|
+
Carapace is released under the MIT License. See LICENSE for details.
|
96
|
+
|
data/Rakefile
ADDED
data/lib/carapace.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
module Carapace
|
2
|
+
|
3
|
+
require 'openssl'
|
4
|
+
include OpenSSL
|
5
|
+
include PKey
|
6
|
+
include Cipher
|
7
|
+
|
8
|
+
@carapace_javascript_written = false
|
9
|
+
|
10
|
+
# Until I can get the below to work it will need to be done in the contoller
|
11
|
+
# helper_method :carapace_javascript
|
12
|
+
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
HEX = { 'a' => 10, 'b' => 11, 'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15 } #:nodoc:
|
17
|
+
|
18
|
+
# Pass as parameter to carapace_decrypt to ensure decryption occurs or force error
|
19
|
+
CARAPACE_FORCE_DECRYPT = true
|
20
|
+
|
21
|
+
# Start a Carapace session.
|
22
|
+
#
|
23
|
+
# A Carapace session allows a Rails action to display and process
|
24
|
+
# an HTML form that returns encrypted fields. The action must start a session
|
25
|
+
# for both the initial display and the post-processing of the request.
|
26
|
+
#
|
27
|
+
# Encryption is performed using a 1024 bit RSA key (or other key
|
28
|
+
# length as specified by the optional parameter)
|
29
|
+
#
|
30
|
+
def carapace_session(key_length=1024) #:doc:
|
31
|
+
unless session[:carapace_private_key]
|
32
|
+
key = RSA.new(key_length)
|
33
|
+
session[:carapace_private_key] = key.to_s
|
34
|
+
session[:carapace_public_modulus] = key.public_key.n.to_s(base=16)
|
35
|
+
session[:carapace_public_exponent] = key.public_key.e.to_s(base=16)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Decrypt a string. The return value is the decrypted string.
|
40
|
+
# If the string was not encrypted by the browser it is returned as-is
|
41
|
+
# unless the force_decrypt parameter is given as CARAPACE_FORCE_DECRYPT
|
42
|
+
# in which case nil is returned
|
43
|
+
#
|
44
|
+
# CARAPACE_FORCE_DECRYPT can be used to protect against accepting plaintext
|
45
|
+
# transmissions when the user's browser has Javascript disabled.
|
46
|
+
#
|
47
|
+
def carapace_decrypt(string, force_decrypt=false) #:doc:
|
48
|
+
if carapace_enabled? then # only decrypt if browser was enabled
|
49
|
+
byte = 0 # the converted byte will go here
|
50
|
+
s = "".rjust(string.length/2) # string to receive converted bytes
|
51
|
+
0.upto(string.length-1) do |i| # iterate through string one chr at a time
|
52
|
+
ch = string[i].chr # current character
|
53
|
+
nibble = HEX[ch] || ch.to_i # converted to its binary value
|
54
|
+
if i%2 == 0 then
|
55
|
+
byte = nibble << 4 # most significant nibble is bits 5-8
|
56
|
+
else
|
57
|
+
byte += nibble # lease significant nibble is bits 1-4
|
58
|
+
s[i/2] = byte # store the converted byte
|
59
|
+
end
|
60
|
+
end
|
61
|
+
RSA.new(session[:carapace_private_key],nil).private_decrypt(s) # perform the decryption
|
62
|
+
else
|
63
|
+
force_decrypt ? nil : string # input is unencrypted - return input
|
64
|
+
end # return error if decryption was forced
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
# Decrypt a string. The return value is the decrypted string
|
69
|
+
# The string is decrypted in-situ, meaning its value is modified
|
70
|
+
# (warning, this does not call any customer accessor (e.g. "password=")
|
71
|
+
# so any custom code (such as password hashing) will not execute.)
|
72
|
+
#
|
73
|
+
def carapace_decrypt!(string, force_decrypt=false) #:doc:
|
74
|
+
decrypted_string = carapace_decrypt(string, force_decrypt)
|
75
|
+
string.replace decrypted_string unless !decrypted_string
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Helper method for use in the view rhtml to insert Carapace Javascript
|
81
|
+
# The javascript is added to a page once, no matter how often this is called.
|
82
|
+
#
|
83
|
+
def carapace_javascript #:doc:
|
84
|
+
unless @carapace_javascript_written
|
85
|
+
session[:carapace_nonce] = Time.now.to_i.to_s.reverse.crypt(rand.to_s.reverse[0,2])
|
86
|
+
@carapace_javascript_written = true
|
87
|
+
return "<script type='text/javascript'>
|
88
|
+
carapace_modulus = \"#{session[:carapace_public_modulus]}\" ;
|
89
|
+
carapace_exponent = \"#{session[:carapace_public_exponent]}\" ;
|
90
|
+
document.cookie = \"carapace_nonce=#{session[:carapace_nonce]}; path=/\";
|
91
|
+
//alert(\"Session:#{session[:carapace_nonce]}\\nCookie:\"+document.cookie)
|
92
|
+
rsa = new RSAKey();
|
93
|
+
rsa.setPublic(carapace_modulus, carapace_exponent);
|
94
|
+
|
95
|
+
function carapace_encrypt(field)
|
96
|
+
{
|
97
|
+
field.value = rsa.encrypt(field.value);
|
98
|
+
}
|
99
|
+
</script>"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns TRUE if Carapace was enabled on the view. This does not mean that
|
104
|
+
# data was encrypted, just that Carapace Javascript was executed by the
|
105
|
+
# user's browser, making the Carapace encryption services available. This
|
106
|
+
# will be TRUE if everything is set up correctly AND the user's browser has
|
107
|
+
# Javascript enabled
|
108
|
+
#
|
109
|
+
# This can be used to protect against accepting plaintext
|
110
|
+
# transmissions when the user's browser has Javascript disabled.
|
111
|
+
#
|
112
|
+
def carapace_enabled? #:doc:
|
113
|
+
cookies["carapace_nonce"]==session[:carapace_nonce]
|
114
|
+
end
|
115
|
+
|
116
|
+
# This is called when Carapace is included in a controller.
|
117
|
+
# It automatically sets upn the Carapace Javascript helper.
|
118
|
+
def self.included(c)
|
119
|
+
#c.RAILS_DEFAULT_LOGGER.debug "Carapace has been included by #{c.class}"
|
120
|
+
if (c.class == Class)
|
121
|
+
c.helper_method :carapace_javascript
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|