<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Stuff… And Things… &#187; security</title>
	<atom:link href="http://stuff-things.net/category/security/feed/" rel="self" type="application/rss+xml" />
	<link>http://stuff-things.net</link>
	<description>Paradise is exactly like where you are right now only much, much better…</description>
	<lastBuildDate>Thu, 03 Jun 2010 00:24:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Generating RSA Key Pairs in Ruby</title>
		<link>http://stuff-things.net/2009/12/11/generating-rsa-key-pairs-in-ruby/</link>
		<comments>http://stuff-things.net/2009/12/11/generating-rsa-key-pairs-in-ruby/#comments</comments>
		<pubDate>Sat, 12 Dec 2009 00:49:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://stuff-things.net/?p=82</guid>
		<description><![CDATA[I&#8217;ve given a number of examples of using Public-key cryptography in blog posts and in the Strongbox documentation, but I&#8217;ve always generated the RSA key pair using the openssl command line tool, i.e.
% openssl genrsa -des3 -out private.pem 2048
Generating RSA private key, 2048 bit long modulus
......+++
.+++
e is 65537 (0x10001)
Enter pass phrase for private.pem:
Verifying - Enter pass [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve given a number of examples of using <a href="http://en.wikipedia.org/wiki/Public-key_cryptography" target="_blank">Public-key cryptography</a> in blog posts and in the <a href="http://github.com/spikex/strongbox" target="_blank">Strongbox</a> documentation, but I&#8217;ve always generated the RSA key pair using the openssl command line tool, i.e.</p>
<pre><code>% openssl genrsa -des3 -out private.pem 2048
Generating RSA private key, 2048 bit long modulus
......+++
.+++
e is 65537 (0x10001)
Enter pass phrase for private.pem:
Verifying - Enter pass phrase for private.pem:
% openssl rsa -in private.pem -out public.pem -outform PEM -pubout
% cat private.pem public.pem > key_pair.pem
</code></pre>
<p>This is fine if you want to generate a key pair once, but what if you want to do it on the fly?  The Ruby OpenSSL library has support for generating key pairs:</p>
<p><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">require &#8216;openssl&#8217;</span></p>
<pre class="ruby">rsa_key = OpenSSL::PKey::RSA.new(2048)</pre>
<p>2048 is the key size, and a good value to use for it.</p>
<p>What&#8217;s not obvious is how to encrypt the private key.   You don&#8217;t <strong>have to</strong> encrypt it, but, if you don&#8217;t, anyone who gets a hold of the key can decrypt your data.  Using an unencrypted private key gives you one layer of security (something you have &#8211; the key), encrypting it gives you an additional layer (something you know &#8211; the password).</p>
<p>To encrypt the private key you need a <a href="http://www.ruby-doc.org/ruby-1.9/classes/OpenSSL/Cipher.html" target="_blank">Cipher</a> object:</p>
<pre class="ruby">cipher =  OpenSSL::Cipher::Cipher.new('des3')</pre>
<p>Then, using the Cipher object, you convert the the key_pair to <a href="http://en.wikipedia.org/wiki/X.509#Certificate_filename_extensions" target="_blank">PEM</a> format:</p>
<pre class="ruby">private_key = rsa_key.to_pem(cipher,'password')
public_key = rsa_key.public_key.to_pem
key_pair = private_key + public_key
</pre>
<p>The resulting PEM strings be saved and then later fed to <a href="http://www.ruby-doc.org/ruby-1.9/classes/OpenSSL/PKey/RSA.html#M006380">OpenSSL::PKey::RSA.new()</a> or used with Strongbox.</p>
]]></content:encoded>
			<wfw:commentRss>http://stuff-things.net/2009/12/11/generating-rsa-key-pairs-in-ruby/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Introducing Strongbox</title>
		<link>http://stuff-things.net/2009/04/17/introducing-strongbox/</link>
		<comments>http://stuff-things.net/2009/04/17/introducing-strongbox/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 16:49:59 +0000</pubDate>
		<dc:creator>Spike</dc:creator>
				<category><![CDATA[Active Record]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://stuff-things.net/?p=44</guid>
		<description><![CDATA[Over a year ago I wrote the wildly popular Encrypting Lots of Sensitive Data with Ruby (on Rails).  At the end I said:
Clearly, this screams for a plugin;  watch this space.
Well, it took a while and it turned out to be a gem, but Strongbox has arrived.
First a recap:
You have a web application [...]]]></description>
			<content:encoded><![CDATA[<p>Over a year ago I wrote the wildly popular <a href="http://stuff-things.net/2008/02/05/encrypting-lots-of-sensitive-data-with-ruby-on-rails">Encrypting Lots of Sensitive Data with Ruby (on Rails)</a>.  At the end I said:</p>
<blockquote><p>Clearly, this screams for a plugin;  watch this space.</p></blockquote>
<p>Well, it took a while and it turned out to be a gem, but <strong><a href="http://github.com/spikex/strongbox">Strongbox</a></strong> has arrived.</p>
<p>First a recap:</p>
<p>You have a web application and you need to encrypt the data your receive from your users.   The most common form of encryption is <a href="http://en.wikipedia.org/wiki/Symmetric_cryptography">symmetric-key encryption</a>, where one password is used for both encryption and decryption.  This works very well, but it means that everyone who enters data needs to know the password and everyone who knows the password can decrypt the data.</p>
<p>Enter <a href="http://en.wikipedia.org/wiki/Public-key_cryptography">Public-key cryptography</a> which used one password (key) to encrypt and a different key to decrypt.   This solves the problem; make the encryption password, the public key, available to your application, and keep  the decryption password, the private key, well, private.  Users don&#8217;t need to know or care how, they fill out a form and the data gets encrypted.  One small problem, size.  The most you can practically encrypt using this method is 245 bytes.  Good enough for the launch codes, but not so for driving directions to the buried treasure.</p>
<p>No problem, if we have larger data, we simply combine the two.  We generate a random password and use it to symmetrically encrypt to data.  We then use the public key to encrypt the random password.  To get the data back, the private key is used to decrypt the random password which is in turn used to decrypt the original data.</p>
<p>Got it?  Good. <a href="http://github.com/spikex/strongbox">Strongbox</a> takes the above three paragraphs and reduces them to this:</p>
<pre>class User &lt; ActiveRecord::Base
  encrypt_with_public_key :secret,
                          :key_pair =&gt; 'path/to/keypair.pem'
end

&gt;&gt; @user = User.new
&gt;&gt; @user.secret = 'Ssssh'
&gt;&gt; @user.secret  # =&gt; "*encrypted*"
&gt;&gt; user.secret.decrypt ‘letmein’ # =&gt; "Ssssh"</pre>
<p>OK, it&#8217;s sightly more complex.   The column &#8220;secret&#8221; needs to exist in the database and be type &#8220;binary&#8221; (more on this in a bit).  In additional, because we are using symmetric encryption (the default), we need two binary columns &#8220;secret_key&#8221; and &#8220;secret_iv&#8221; to store the generated symmetric key and <a href="http://en.wikipedia.org/wiki/Initialization_vector">Initialization vector (IV)</a> (which you can think of as a second key (but it&#8217;s <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation">not</a>) once they are encrypted with the public key.</p>
<p>If you are certain that the data you are encrypting won&#8217;t be larger than 245 bytes, you can use the following:</p>
<pre>class User &lt; ActiveRecord::Base
  encrypt_with_public_key :secret,
                          :key_pair =&gt; 'path/to/keypair.pem',
                          :symmetric =&gt; :never
  validates_length_of :secret, :maximum=&gt; 245
end</pre>
<p>This skips the symmetric encryption, is faster, and you only need the binary &#8220;secret&#8221; column.</p>
<p>You&#8217;ll also need to generate a key pair.  Be sure to choose a strong pass phrase, as this is the one that will decrypt everything (as always, I suggest using <a href="http://world.std.com/~reinhold/diceware.html">Diceware</a>).</p>
<pre><code>
% openssl genrsa -des3 -out private.pem 2048
Generating RSA private key, 2048 bit long modulus
......+++
.+++
e is 65537 (0x10001)
Enter pass phrase for key_pair.pem:
Verifying - Enter pass phrase for key_pair.pem:
</code></pre>
<p>If you aren&#8217;t going to be decrypting data on a regular basis you might want to deploy just the public key.  Extract it:</p>
<pre><code>
mv key_pair.pem private.pem
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
Enter pass phrase for private.pem:
writing RSA key
</code></pre>
<p>And change your model:</p>
<pre>class User &lt; ActiveRecord::Base
  encrypt_with_public_key :secret,
                          :public_key =&gt; 'path/to/public.pem'
                          :private_key =&gt; 'path/to/private.pem'
end</pre>
<p>You could then have rake/Capistrano task to deploy and remove the private key as needed.  Or you could limit it&#8217;s use to a separate, non-public, server.</p>
<p>As noted  above you want your database column(s) to be binary.  If your database does not have a binary type you can add the <em>:base64</em> option:</p>
<pre>class User &lt; ActiveRecord::Base
  encrypt_with_public_key :secret,
                          :key_pair =&gt; 'path/to/keypair.pem',
                          :base64 =&gt; :true
end</pre>
<p>This will convert the binary data to text using Base64.  You must, <strong>must</strong> make your column type &#8220;text&#8221;.   Base64 increases the length of the data it encodes by approximately 137%.  Type &#8220;string&#8221; is typically 256 bytes, 245 * 1.37 = 335.65 bytes.   <em>If you use a &#8220;string&#8221; column and encrypt anything greater than 186 bytes <strong>your data will be lost</strong></em>.</p>
<p>Finally, there are two addition options for tweaking the encryption settings that you are unlikely to need:</p>
<p>&#8220;:symmetric_cipher&#8221; lets you change the algorithm that&#8217;s used for symmetric encryption.  The default is 256 bit <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">Advanced Encryption Standard</a> (AES) using  <a href="http://en.wikipedia.org/wiki/Cipher_block_chaining">Cipher Block Chaining</a> (CBC) (&#8216;aes-256-cbc&#8217; in OpenSSL terms).   AES has been approved by the NSA for top secret information, so it&#8217;s probably good enough, but <a href="http://en.wikipedia.org/wiki/Blowfish_(cipher)">Blowfish</a> (&#8216;bf-cbc&#8217;) is know to work as well.  <a href="http://www.openssl.org/docs/apps/enc.html">Other ciphers in CBC mode</a> should also work, but have not been tested by me.  (Note that all ciphers may not be supported by your version of OpenSSL, &#8220;openssl list-cipher-commands&#8221; will provide a list.)</p>
<p>&#8220;:padding&#8221; allows you to change the method used to pad data encrypted with the public key.   Unless you are working with legacy data, you shouldn&#8217;t need to change this.  The default is &#8220;RSA_PKCS1_PADDING&#8221;, see the code if you need other options.</p>
<p><strong>Disclaimer</strong></p>
<p>I am not a security expert.  This software using an off the shelf encryption tool, namely <a href="http://www.openssl.org/">OpenSSL</a>, that has been well tested, but that is not a guarantee that this implementation doesn&#8217;t have weakness.  Be sure you understand what <em>Strongbox</em> does, and review it for your application.  A few things to keep in mind:</p>
<ul>
<li><em>Strongbox</em> encrypts the data as it is saved, but no sooner.  Be sure to use HTTPS for submitting the forms (and decrypting data!).</li>
<li>If an attacker gains entry to your system the encryption should protect your data.   However, they might be able to hack your code to intercept new data or, much worse, your private key password.  Protect your server.</li>
<li>When decrypting make sure your data isn&#8217;t cached.</li>
</ul>
<p>And test, test, test.  If there is a problem with how your data is encrypted, there is no getting it back.</p>
<p>One concern I have is garbage collection.  If you decrypt something into a variable which then goes out of scope, how long does it hang around in memory?  Can you force it out?  I haven&#8217;t found much information on this; if there are any Ruby GC experts out there, share your knowledge!</p>
<p>I am always open to suggestions and improvement, but, to quote the License:</p>
<blockquote><p>THE SOFTWARE IS PROVIDED &#8220;AS IS&#8221;, WITHOUT WARRANTY OF ANY<br />
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE<br />
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR<br />
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE<br />
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,<br />
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF<br />
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<br />
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER<br />
DEALINGS IN THE SOFTWARE.</p></blockquote>
<p>So there!</p>
<p>Finally, I&#8217;d like to give a shout-out to <a href="http://www.thoughtbot.com/">thoughtbot</a>.    While this software has existed for many years, the final form of the gem was greatly inspired by <a href="http://www.thoughtbot.com/projects/paperclip">Paperclip</a>.   It&#8217;s a nice example of an approach to adding complex features to an ActiveRecord attribute and how to test them.   In additional, the gem sat unpublished for nearly a year because it needed test coverage and my testing was week.  Then I took thoughtbot&#8217;s <a href="http://www.thoughtbot.com/services/training/advanced-ruby-on-rails-boston">Advanced Ruby on Rails</a> class which really helped me get my head around testing and TDD, and got this moving again.  If you know Rails, but need to improve your processes, I highly recommend this class.</p>
]]></content:encoded>
			<wfw:commentRss>http://stuff-things.net/2009/04/17/introducing-strongbox/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Encrypting Lots of Sensitive Data with Ruby (on Rails)</title>
		<link>http://stuff-things.net/2008/02/05/encrypting-lots-of-sensitive-data-with-ruby-on-rails/</link>
		<comments>http://stuff-things.net/2008/02/05/encrypting-lots-of-sensitive-data-with-ruby-on-rails/#comments</comments>
		<pubDate>Tue, 05 Feb 2008 18:26:10 +0000</pubDate>
		<dc:creator>Spike</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://stuff-things.net/2008/02/05/encrypting-lots-of-sensitive-data-with-ruby-on-rails/</guid>
		<description><![CDATA[Previously I wrote about how to use public key encryption to automatically encrypt data using Ruby (and thus Rails).  Because this method can encrypt data without a password, it&#8217;s very useful for securing information received from a form, without the person entering the from having to do anything special.   However public key [...]]]></description>
			<content:encoded><![CDATA[<p>Previously I wrote about how to use public key encryption to automatically encrypt data using Ruby (and thus Rails).  Because this method can encrypt data without a password, it&#8217;s very useful for securing information received from a form, without the person entering the from having to do anything special.   However public key encryption has limits; the amount of data you can encrypt with this method is limited by the key size you use, and, that after a point increasing the key size isn&#8217;t a practical an option.  We solve this problem using a combination of public key encryption and <a href="http://en.wikipedia.org/wiki/Symmetric_cryptography">symmetric-key encryption</a>.</p>
<p>First a little theory; and when I say &#8220;a little&#8221; I mean it.  Under the hood encryption is a headache inducing branch of mathematics.  If you want to the literal truth, there is plenty of good reading out there.</p>
<p>Symmetric-key cryptography is what people tend to think of when, and if, they think of encryption.  A password is used to encrypt some information, and that same password must be entered to retrieve the information.  Under the hood is an algorithm or <em>cipher</em>, which simply put, is a mathematical function that transforms the data into something obscure and then back again.  For our purpose we need a <a href="http://en.wikipedia.org/wiki/Block_cipher">block ciphers</a>.<br />
A block cipher takes a small, typically 128 or 256 bit, chunk of data and encrypts it.  There are many, but in this example we&#8217;ll use the <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">Advanced Encryption Standard</a> which is the de facto standard.</p>
<p>(There also exist <a href="http://en.wikipedia.org/wiki/Stream_cipher">stream ciphers</a> which work on streams of data, encrypting a phone call for example, but that trade security for speed and can be difficult to use correctly.)</p>
<p>We also need a little glue.  Because block ciphers operate on small chunks of data, they need to be applied again and again.   However give the same input data the cipher will always produce the same encrypted output;  any redundancies in the input will be exposed as redundancies  in the output and make in vulnerable to a number of attacks.  To avoid this we use a <em>mode of operation</em> called <a href="http://en.wikipedia.org/wiki/Cipher_block_chaining">Cipher Block Chaining</a>.  CBC using data from one block to further obfuscate the data in the next, effectively hiding any redundancies.</p>
<p>While simple and secure, using symmetric-key cryptography can be problematic; everyone needs to know the password to encrypt data and everyone who has the password (or as the pros say, <em>shared secret key</em>) can decrypt data.   This works well if you small set of people who need to know the password and a secure way to distribute it (over drinks in a dark corner of a seedy bar is poetic, if not necessarily secure) but in the case of a web site with hundreds or thousands of people entering data, it&#8217;s not practical.</p>
<p><a href="http://en.wikipedia.org/wiki/Public-key_cryptography">Public-key cryptography</a> can be thought of as Symmetric-key encryption with two passwords, or keys, called a <em>key pair</em>.  One, the <em>public key</em>, that encrypts data and another, <em>the private key</em> that decrypts.   Because the public key can not be used to decrypt data it encrypts it can be safely given out or installed on a web site, allowing anyone to encrypt data to be sent to the owner of the key.  The private key is kept safe and is typically symmetric encrypted with an additional password</p>
<p>The solution is actually quite simple.  We generate a random password and use that for the symmetric-key encryption.  We then encrypt the random password using the public key, and store both the encrypted password, and encrypted data.   When we need to get at the data, we use the private key, and its password to decrypt the random password which, in turn, is used to decrypt the data.</p>
<p>Well, it&#8217;s almost that simple.  In order to randomize the data, the CBC <em>glue</em> requires a <a href="http://en.wikipedia.org/wiki/Initialization_vector">Initialization vector (IV)</a>.  This <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation">article</a> has a good explanation of why, but for our purposes we can just think of it as a second random password we need to encrypt and save.</p>
<p>OK, enough talk, let&#8217;s  encrypt some text:</p>
<pre name="code" class="ruby">
# OpenSSL provides both symmetric and public key encryption
require 'openssl'

# Encrypt with 256 bit AES with CBC
cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
cipher.encrypt # We are encypting
# The OpenSSL library will generate random keys and IVs
cipher.key = random_key = cipher.random_key
cipher.iv = random_iv = cipher.random_iv

encrypted_data = cipher.update(plain_data) # Encrypt the data.
encrypted_data &lt;&lt; cipher.final
</pre>
<p>At this point we could just save <em>encrypted_data</em> in the database and it would be well protected.  So well in fact that we couldn&#8217;t get it back.  To do that we&#8217;re going to need to save the random password and IV.</p>
<p>Generate a key pair.  Be sure to choose a good password as this is the one that will decrypt everything.</p>
<pre>
<code>
% openssl genrsa -des3 -out private.pem 2048
Generating RSA private key, 2048 bit long modulus
......+++
.+++
e is 65537 (0x10001)
Enter pass phrase for private.pem:
Verifying - Enter pass phrase for private.pem:
</code>
</pre>
<p>Now extract the public key:</p>
<pre>
<code>
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
Enter pass phrase for private.pem:
writing RSA key
</code>
</pre>
<p>See my <a href="http://stuff-things.net/2007/06/11/encrypting-sensitive-data-with-ruby-on-rails/">previous article</a> for more details on what we&#8217;re doing here.</p>
<p>Now we can use the public key to encrypt the random key and IV:</p>
<pre name="code" class="ruby" width="800">
public_key_file = 'public.pem';

public_key = OpenSSL::PKey::RSA.new(File.read(public_key_file))

encrypted_key = public_key.public_encrypt(random_key)
encrypted_iv = public_key.public_encrypt(random_iv)
</pre>
<p>Now if we store all three pieces,  <em>encrypted_key</em>, <em>encrypted_iv</em>,  and <em>encrypted_data</em> we have successfully encrypted our original data.</p>
<p>Of course we&#8217;ll want to get that data back, and to do so we reverse the process:</p>
<pre name="code" class="ruby" width="800">
require 'openssl'

private_key_file = 'private.pem';

private_key =
   OpenSSL::PKey::RSA.new(File.read(private_key_file),password)

cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
cipher.decrypt
cipher.key = private_key.private_decrypt(encrypted_key)
cipher.iv = private_key.private_decrypt(encrypted_iv)

decrypted_data = cipher.update(encrypted_data)
decrypted_data &lt;&lt; cipher.final
</pre>
<p><em>password</em> is the password you used when generating the key-pair.</p>
<p>Now let&#8217;s put it all together in an Active Record model:</p>
<pre name="code" class="ruby" width="800">
class Sensitive &lt; ActiveRecord::Base

  attr_accessor :plain_data
  attr_protected :encrypted_data, :encrypted_key, :encrypted_iv
  before_save :encrypt_sensitive

  def decrypt_sensitive(password)
    if self.encrypted_data
      private_key = OpenSSL::PKey::RSA.new(File.read(APP_CONFIG['private_key']),password)
      cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
      cipher.decrypt
      cipher.key = private_key.private_decrypt(self.encrypted_key)
      cipher.iv = private_key.private_decrypt(self.encrypted_iv)

      decrypted_data = cipher.update(self.encrypted_data)
      decrypted_data &lt;&lt; cipher.final
    else
      ''
    end
  end

  def clear_sensitive
    self.encrypted_data = self.encrypted_key = self.encrypted_iv = nil
  end

  private

  def encrypt_sensitive
    if !self.plain_data.blank?
      public_key = OpenSSL::PKey::RSA.new(File.read(APP_CONFIG['public_key']))
      cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
      cipher.encrypt
      cipher.key = random_key = cipher.random_key
      cipher.iv = random_iv = cipher.random_iv

      self.encrypted_data = cipher.update(self.plain_data)
      self.encrypted_data &lt;&lt; cipher.final

      self.encrypted_key =  public_key.public_encrypt(random_key)
      self.encrypted_iv = public_key.public_encrypt(random_iv)
    end
  end
end
</pre>
<p>When creating or updating your model you don&#8217;t have to do anything, if &#8220;plain_data&#8221; is present it will be automatically encrypted.  When you want to view the plain text you call &#8220;@record.decrypt_sensitive(&#8216;passwd&#8217;)&#8221;; that could be done with a little AJAX that prompts for a password and populates the &#8220;plain_data&#8221; field.  The encrypted data is only updated when &#8220;plain_data&#8221; is present.  This done so that the record can be updated without decrypting (and re-encrypting) encrypted data (handy in an application were not everyone has access to the sensitive data).  To actually clear the   encrypted data call &#8220;@record.clear_sensitive&#8221; and then save.</p>
<p>Setting up the APP_CONFIG hash is left as an exercise for the reader.</p>
<p>Clearly, this screams for a plugin;  watch this space.</p>
]]></content:encoded>
			<wfw:commentRss>http://stuff-things.net/2008/02/05/encrypting-lots-of-sensitive-data-with-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Encrypting Sensitive Data with Ruby (on Rails)</title>
		<link>http://stuff-things.net/2007/06/11/encrypting-sensitive-data-with-ruby-on-rails/</link>
		<comments>http://stuff-things.net/2007/06/11/encrypting-sensitive-data-with-ruby-on-rails/#comments</comments>
		<pubDate>Mon, 11 Jun 2007 17:02:08 +0000</pubDate>
		<dc:creator>Spike</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://stuff-things.net/2007/06/11/encrypting-sensitive-data-with-ruby-on-rails/</guid>
		<description><![CDATA[In Encrypting Sensitive Data with Perl I wrote about how to use public key encryption to automatically and securely encrypt information with Perl.  This allows you encryption things like credit card numbers, bank routing information, or that winning PowerBall number in a unattended fashion.   Typically, you would use this in a situation [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://stuff-things.net/2007/05/02/encrypting-sensitive-data-with-perl/">Encrypting Sensitive Data with Perl</a> I wrote about how to use <a href="http://en.wikipedia.org/wiki/Public-key_cryptography">public key encryption</a> to automatically and securely encrypt information with Perl.  This allows you encryption things like credit card numbers, bank routing information, or that winning PowerBall number in a unattended fashion.   Typically, you would use this in a situation where a user needs to enter sensitive information into a form which need to be stored in a secure manner.   We can do this with Ruby (on Rails) as well, and it&#8217;s even easier.</p>
<p>First we need to generate a key pair.  This creates two keys, a public key which will only be used to encrypt data, and a private key, which will only be used to decrypt data.  The private key is protected by a password know only to us.  When it comes to choosing strong passwords, I suggest using <a href="http://world.std.com/~reinhold/diceware.html">Diceware</a>.  <em>2048</em> is the key size in bits.  Bigger is better, but also slower;  2048 is considered a good trade off between speed and encryption strength.  We are also limited by this to encrypting as most 2048 bits, more on this below.</p>
<pre>
<code>
% openssl genrsa -des3 -out private.pem 2048
Generating RSA private key, 2048 bit long modulus
......+++
.+++
e is 65537 (0x10001)
Enter pass phrase for private.pem:
Verifying - Enter pass phrase for private.pem:
</code>
</pre>
<p>Then we extract the public key:</p>
<pre>
<code>
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
Enter pass phrase for private.pem:
writing RSA key
</code>
</pre>
<p>Once we have the keys, we can encrypt data using the following:</p>
<pre name="code" class="ruby">
#!/usr/bin/env ruby

require 'openssl'
require 'base64'

public_key_file = 'public.pem';
string = 'Hello World!';

public_key =
   OpenSSL::PKey::RSA.new(File.read(public_key_file))
encrypted_string =
   Base64.encode64(public_key.public_encrypt(string))

print encrypted_string, "\n"
</pre>
<p>Simply, <em>public_key_file</em> is path to the file containing the public key, and <em>string</em> is the string to encrypt.  We open the public key and then use <em>public_encrypt</em> to encrypt it.  Because the encrypted string is binary I have converted to text using <a href="http://en.wikipedia.org/wiki/Base64">Base64</a>.  If your are storing the encrypted string in a database that can hold binary data, you could change:</p>
<pre><code>encrypted_string = Base64.encode64(public_key.public_encrypt(string))</code></pre>
<p>to:</p>
<pre><code>encrypted_string = public_key.public_encrypt(string)</code></pre>
<p>Now that we have encrypted data, we&#8217;ll want to be able to get it back.</p>
<pre name="code" class="ruby">
#!/usr/bin/env ruby

require 'openssl'
require 'base64'

private_key_file = 'private.pem';
password = 'boost facile'

encrypted_string = %Q{
qBF3gjF8iKhDh+g+TOvAzBkJA/1d2lD8RUyz2Ol+s1OpLB5aA3RA7EHm0KGL
XaP3upvJ7I5rN1yO9Qat9kyRQu9OMqAUmFvwUaiW/1NPjxnpmcFn9mhkttP9
qfO6iIfyxErUqKIxHYqavyPmivre9eEcXiBdtIK6NJJKG3WmSfIFgpZ6eBWI
wxlZg+x0fI4L2JsODMGx5Khn7CUt0bTkH6HMHwxEG24NbsmrqtC2zn8Hm/87
UyN5ZCDyJ/mtIHAjzPry6vbVPTF0QCR4lZ7uSt/W7JZ0tNgX7eQQwoPCgbqU
/uwRCwww/c407jw7YEE5Lgpx20/jyLXJwvZHxNEcxA==
}

private_key =
  OpenSSL::PKey::RSA.new(File.read(private_key_file),password)

string =
  private_key.private_decrypt(Base64.decode64(encrypted_string))

print string, "\n"
</pre>
<p>Here <em>private_key_file</em> is path to the file containing the private key, <em>password</em> and <em>encrypted_string</em> is the string to decrypt.  In a real application you would not want to hard-code the password, rather you should prompt for it in some way.</p>
<p>Again we are using Base64 to make the encrypted string human readable.  If this is not necessary, change:</p>
<pre><code>string = private_key.private_decrypt(Base64.decode64(encrypted_string))</code></pre>
<p>to:</p>
<pre><code>string = private_key.private_decrypt(encrypted_string)</code></pre>
<p>As noted above, you can not use this method to encrypt anything larger than the key size minus 11 bytes of overhead (<a href="http://en.wikipedia.org/wiki/Padding_%28cryptography%29">padding</a>).  In this case we have a 2048 bit key which gives 256 &#8211; 11 = 245 bytes.   The temptation is to increase the key size to accommodate more data, but this quickly become to slow to be useful.  The correct way to accomplish this is to use public key encryption to encrypt random password, which, in turn is used to encrypt the data using <a href="http://en.wikipedia.org/wiki/Symmetric_cryptography">symmetric-key encryption</a>.   I&#8217;ll cover this next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://stuff-things.net/2007/06/11/encrypting-sensitive-data-with-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Encrypting Sensitive Data with Perl</title>
		<link>http://stuff-things.net/2007/05/02/encrypting-sensitive-data-with-perl/</link>
		<comments>http://stuff-things.net/2007/05/02/encrypting-sensitive-data-with-perl/#comments</comments>
		<pubDate>Wed, 02 May 2007 20:56:23 +0000</pubDate>
		<dc:creator>Spike</dc:creator>
				<category><![CDATA[CGI]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://stuff-things.net/2007/05/02/encrypting-sensitive-data-with-perl/</guid>
		<description><![CDATA[It&#8217;s not uncommon to have information submitted through a web form that you need to save, but don&#8217;t want to have lying around in plain text.  Credit card numbers, bank routing information, missile launch codes, and so on.   The trick is to do this in a unattended fashion; you don&#8217;t want to [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s not uncommon to have information submitted through a web form that you need to save, but don&#8217;t want to have lying around in plain text.  Credit card numbers, bank routing information, missile launch codes, and so on.   The trick is to do this in a unattended fashion; you don&#8217;t want to have the person submitting the form do anything special such as supply a password.  Enter <a href="http://en.wikipedia.org/wiki/Public-key_cryptography">public key encryption</a>.</p>
<p>In public key encryption there are two passwords, or keys, one which is used to encrypt information and one which is used to decrypt (there are additional ways to use the key pair, but that&#8217;s a topic for another day).  Since the encryption key can not be used to decrypt sensitive data, can safely be made public.  So in the case of a web form, we can make the public key available to our CGI, which protecting the private key for our use only.</p>
<p>The first step is to generate a key pair and password protect the private key.  For this we&#8217;ll use <a href="http://www.openssl.org/">OpenSSL</a> which comes pre-installed on just about every Unix-like system (including OS X).  OpenSSL provides a wide range of cryptographic functions including an implementation of the <a href="http://en.wikipedia.org/wiki/RSA">RSA</a> public key encryption algorithm.</p>
<p>First we generate the private key.  &#8220;2048&#8243; is the size of the key in bits, and, in this simple example, it controls the maximum number of bits we can encrypt .  For more security, at the cost of more processor overhead, you can increase size, but you shouldn&#8217;t use a smaller number.   We&#8217;ll need a password; I like to use <a href="http://world.std.com/~reinhold/diceware.html">Diceware</a>, but you can generate it any way you like.</p>
<p><code><br />
% openssl genrsa -des3 -out private.pem 2048<br />
Generating RSA private key, 2048 bit long modulus<br />
......+++<br />
.+++<br />
e is 65537 (0x10001)<br />
Enter pass phrase for private.pem:<br />
Verifying - Enter pass phrase for private.pem:<br />
</code></p>
<p>Then we extract the public key:</p>
<p><code><br />
openssl rsa -in private.pem -out public.pem -outform PEM -pubout<br />
Enter pass phrase for private.pem:<br />
writing RSA key<br />
</code></p>
<p>Now a bit of code to encrypt a string using the public key:</p>
<pre name="code" class="ruby">
#!/usr/bin/perl

use Crypt::OpenSSL::RSA;
use MIME::Base64;
use strict;

my $public_key = 'public.pem';
my $string = 'Hello World!';

print encryptPublic($public_key,$string);

exit;

sub encryptPublic {
  my ($public_key,$string) = @_;

  my $key_string;
  open(PUB,$public_key) || die "$public_key: $!";
  read(PUB,$key_string,-s PUB); # Suck in the whole file
  close(PUB);

  my $public =
          Crypt::OpenSSL::RSA-&gt;new_public_key($key_string);
  encode_base64($public-&gt;encrypt($string));
}
</pre>
<p>The function <em>encryptPublic</em> takes the path of the public key and a string to encrypt and returns the encrypt string.  Because the encrypted string is binary it&#8217;s converted to text using <a href="http://en.wikipedia.org/wiki/Base64">Base64</a> to make it easier to handle.  This is certainly not necessary, and if you were storing the string in a database that has a binary type you could change the last line of the function to:</p>
<p><code>  $public-&gt;encrypt($string)</code></p>
<p>The code requires the CPAN module &#8220;Crypt::OpenSSL::RSA&#8221; which is a wrapper around the OpenSSL libraries.</p>
<p>Now to decrypt:</p>
<pre name="code" class="ruby">
#!/usr/bin/perl

use Convert::PEM;
use Crypt::OpenSSL::RSA;
use MIME::Base64;
use strict;

my $encrypted_string =q(
P0/HHc8oo1vmUoeUbtF6EKqyptudy7XyWTtCuPXP8wZDKTO8K/pZ/77/EAz8HV4VJaL0KdMVm7iD
kCpsrS6Wg/gyKIzVwBE/bN5w8SwAGH93zUs4Vb0QsogJExHKvjY5KNE5FovdtPfUIwFJdcddK2M9
aLeDixCSb8T31rlJ5sRKCObQJ/M9Co1nSWBAtVufBREJPYYeLPZsw2DTFpsT5WAMuv9BpU4dViiT
U+2DmJFr0awzV3NthGVoKXVw2toVbiaAXK2Hot/0CFvbwD8YeKGc2HsCGZS6jdOHKhy8HJWqKPCy
gPbWtSSugV04m66JV7oxcHbf2NhLpg3HfeWluQ==
);

my $private_key = 'private.pem';

my $password = 'boost facile';

print decryptPrivate($private_key,$password,$encrypted_string),  "\n";

exit;

sub decryptPrivate {
  my ($private_key,$password,$string) = @_;
  my $key_string = readPrivateKey($private_key,$password);

  return(undef) unless ($key_string); # Decrypt failed.
  my $private = Crypt::OpenSSL::RSA-&gt;new_private_key($key_string) ||
  die "$!";

  $private-&gt;decrypt(decode_base64($string));
}

sub readPrivateKey {
  my ($file,$password) = @_;
  my $key_string;
  $key_string = decryptPEM($file,$password);
}

sub decryptPEM {
  my ($file,$password) = @_;

  my $pem = Convert::PEM-&gt;new(
                              Name =&gt; 'RSA PRIVATE KEY',
                              ASN  =&gt; qq(
                  RSAPrivateKey SEQUENCE {
                      version INTEGER,
                      n INTEGER,
                      e INTEGER,
                      d INTEGER,
                      p INTEGER,
                      q INTEGER,
                      dp INTEGER,
                      dq INTEGER,
                      iqmp INTEGER
                  }
           ));

  my $pkey =
    $pem-&gt;read(Filename =&gt; $file, Password =&gt; $password);

  return(undef) unless ($pkey); # Decrypt failed.
  $pem-&gt;encode(Content =&gt; $pkey);
}
</pre>
<p>Here we have the function <em>decryptPrivate</em> which takes the path of the private key file, the private key password, and the (Base64 encoded) encrypted string and returns the decrypted string.   The process is a bit more complex than encryption and, do to the limitations of  &#8220;Crypt::OpenSSL::RSA&#8221;, we have to use an additional CPAN module, &#8220;Convert::PEM&#8221;.</p>
<p>Crypt::OpenSSL::RSA&#8221; lacks the ability to unlock (decrypt) the private key.  It&#8217;s decrypt function expects to receive an already decrypted copy of the key.  Fortunately for us &#8220;Convert::PEM&#8221; can decrypt the private key and return it in a format we can use.</p>
<p>As with encryption, you do not need to use Base64 encoded strings.  Simply replace the line:</p>
<p><code>  $private-&gt;decrypt(decode_base64($string));</code></p>
<p>with:</p>
<p><code>  $private-&gt;decrypt($string);</code></p>
<p>On key size:  As I said above the amount of data you can encrypt this way is limited by the key size minus 11 bytes of overhead (<a href="http://en.wikipedia.org/wiki/Padding_%28cryptography%29">padding</a>), here a 2048 bit key gives us 256 &#8211; 11 = 245 bytes.  You could handle larger data by increasing the key size, but that would entail a potentially large performance hit and is not how key pairs are used.  Instead you would generate a random password, use it to encrypt the data using <a href="http://en.wikipedia.org/wiki/Symmetric_cryptography">symmetric-key encryption</a> such as <a href="http://en.wikipedia.org/wiki/Triple_DES">Triple DES</a> or <a href="http://en.wikipedia.org/wiki/Blowfish_%28cipher%29">Blowfish</a>, then use the public key to encrypt and store the random password.</p>
<p>One last note; there is another Perl Module &#8220;Crypt::RSA&#8221; which is a purl perl implementation of RSA public key encryption.  On the plus side, it doesn&#8217;t require OpenSSL be installed and it has a much more complete API, including better key handling.  On the minus side, while fast for perl, it&#8217;s considerably slower than OpenSSL and can not take advantage of encryption hardware; something that OpenSSL automatically does.</p>
]]></content:encoded>
			<wfw:commentRss>http://stuff-things.net/2007/05/02/encrypting-sensitive-data-with-perl/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
