Friday, February 03, 2012

[Rails] Good Random Positive Integer

Tonight I needed a quick way to generate a good pseudo random number.  The following statement in Ruby will generate a positive integer between 0 and the maximum integer supported on the system.
SecureRandom.random_number((2**(0.size * 8-2)-1))
Running that 10 times as a test on my system returned:
  • 479960941838047707
  • 4598189742420362323
  • 4319555246297899788
  • 79907720343840910
  • 1019099276589074756
  • 1753578159791031009
  • 51485412595337811
  • 3333462064391733874
  • 2622897372121370782
  • 4287564549349999056
That's all for tonight.

Sources




Friday, January 27, 2012

OpenSSL: Generating an RSA Key from the Command Line

A few of weeks ago, I posted about how to Encrypt a File with a Password from the Command Line using OpenSSL. While very useful in its own right, the real power of the OpenSSL library is its ability to support the use of public key cryptograph for encrypting or validating data in an unattended manner (where the password is not required to encrypt) is done with public keys.

The Commands to Run

You can generate a pubic and private RSA key pair like this:
openssl genrsa -des3 -out private.pem 2048
That generates a 2048-bit RSA key pair, encrypts them with a password you provide, and writes them to a file. You need to next extract the public key file. You will use this, for instance, on your web server to encrypt content so that it can only be read with the private key:
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
The Generated Key Files

The generated files are base64-encoded encryption keys in plain text format.  If you select a password for your private key, its file will be encrypted with your password.  Be sure to remember this password or the key pair becomes useless.

The private.pem file looks something like this:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,32495A90F3FF199D
lrMAsSjjkKiRxGdgR8p5kZJj0AFgdWYa3OT2snIXnN5+/p7j13PSkseUcrAFyokc
V9pgeDfitAhb9lpdjxjjuxRcuQjBfmNVLPF9MFyNOvhrprGNukUh/12oSKO9dFEt
s39F/2h6Ld5IQrGt3gZaBB1aGO+tw3ill1VBy2zGPIDeuSz6DS3GG/oQ2gLSSMP4
OVfQ32Oajo496iHRkdIh/7Hho7BNzMYr1GxrYTcE9/Znr6xgeSdNT37CCeCH8cmP
aEAUgSMTeIMVSpILwkKeNvBURic1EWaqXRgPRIWK0vNyOCs/+jNoFISnV4pu1ROF
92vayHDNSVw9wHcdSQ75XSE4Msawqv5U1iI7e2lD64uo1qhmJdrPcXDJQCiDbh+F
hQhF+wAoLRvMNwwhg+LttL8vXqMDQl3olsWSvWPs6b/MZpB0qwd1bklzA6P+PeAU
sfOvTqi9edIOfKqvXqTXEhBP8qC7ZtOKLGnryZb7W04SSVrNtuJUFRcLiqu+w/F/
MSxGSGalYpzIZ1B5HLQqISgWMXdbt39uMeeooeZjkuI3VIllFjtybecjPR9ZYQPt
FFEP1XqNXjLFmGh84TXtvGLWretWM1OZmN8UKKUeATqrr7zuh5AYGAIbXd8BvweL
Pigl9ei0hTculPqohvkoc5x1srPBvzHrirGlxOYjW3fc4kDgZpy+6ik5k5g7JWQD
lbXCRz3HGazgUPeiwUr06a52vhgT7QuNIUZqdHb4IfCYs2pQTLHzQjAqvVk1mm2D
kh4myIcTtf69BFcu/Wuptm3NaKd1nwk1squR6psvcTXOWII81pstnxNYkrokx4r2
7YVllNruOD+cMDNZbIG2CwT6V9ukIS8tl9EJp8eyb0a1uAEc22BNOjYHPF50beWF
ukf3uc0SA+G3zhmXCM5sMf5OxVjKr5jgcir7kySY5KbmG71omYhczgr4H0qgxYo9
Zyj2wMKrTHLfFOpd4OOEun9Gi3srqlKZep7Hj7gNyUwZu1qiBvElmBVmp0HJxT0N
mktuaVbaFgBsTS0/us1EqWvCA4REh1Ut/NoA9oG3JFt0lGDstTw1j+orDmIHOmSu
7FKYzr0uCz14AkLMSOixdPD1F0YyED1NMVnRVXw77HiAFGmb0CDi2KEg70pEKpn3
ksa8oe0MQi6oEwlMsAxVTXOB1wblTBuSBeaECzTzWE+/DHF+QQfQi8kAjjSdmmMJ
yN+shdBWHYRGYnxRkTatONhcDBIY7sZV7wolYHz/rf7dpYUZf37vdQnYV8FpO1um
Ya0GslyRJ5GqMBfDS1cQKne+FvVHxEE2YqEGBcOYhx/JI2soE8aA8W4XffN+DoEy
ZkinJ/+BOwJ/zUI9GZtwB4JXqbNEE+j7r7/fJO9KxfPp4MPK4YWu0H0EUWONpVwe
TWtbRhQUCOe4PVSC/Vv1pstvMD/D+E/0L4GQNHxr+xyFxuvILty5lvFTxoAVYpqD
u8gNhk3NWefTrlSkhY4N+tPP6o7E4t3y40nOA/d9qaqiid+lYcIDB0cJTpZvgeeQ
ijohxY3PHruU4vVZa37ITQnco9az6lsy18vbU0bOyK2fEZ2R9XVO8fH11jiV8oGH
-----END RSA PRIVATE KEY-----
and the public key, public.pem, file looks like:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxzYuc22QSst/dS7geYYK
5l5kLxU0tayNdixkEQ17ix+CUcUbKIsnyftZxaCYT46rQtXgCaYRdJcbB3hmyrOa
vkhTpX79xJZnQmfuamMbZBqitvscxW9zRR9tBUL6vdi/0rpoUwPMEh8+Bw7CgYR0
FK0DhWYBNDfe9HKcyZEv3max8Cdq18htxjEsdYO0iwzhtKRXomBWTdhD5ykd/fAC
VTr4+KEY+IeLvubHVmLUhbE5NgWXxrRpGasDqzKhCTmsa2Ysf712rl57SlH0Wz/M
r3F7aM9YpErzeYLrl0GhQr9BVJxOvXcVd4kmY+XkiCcrkyS1cnghnllh+LCwQu1s
YwIDAQAB
-----END PUBLIC KEY-----
Protecting Your Keys
  • Depending on the nature of the information you will protect, it's important to keep the private key backed up and secret. 
  • The public key can be distributed anywhere or embedded in your web application scripts, such as in your PHP, Ruby, or other scripts. 
  • Again, backup your keys!
    • Remember, if the key goes away the data encrypted to it is gone.
    • Keeping a printed copy of the key material in a sealed envelope in a bank safety deposit box is a good way to protect important keys against loss due to fire or hard drive failure.


But!  How do I use this Key?


Don't worry, I will write about how to use your freshly minted RSA keys in a future blog post.  In the mean time checkout the PHP functionality at http://us2.php.net/openssl_seal.  Hint, you can use your new public key with openssl_seal.


I hope this helps!


Oh, and one last thing.  If you, dear reader, were planning any funny business with the private key that I have just published here.  Know that they were made especially for this series of blog posts. I do not use them for anything else.

Tuesday, January 24, 2012

Rails: Point DNS to 127.0.0.1 to Test Wildcard Subdomains on WEBrick

Want quick method for testing domain/subdomain-based routing logic in your Rails applications? Point a subdomain and wildcard subdomain of your company's DNS to 127.0.0.1, your localhost IP address.

Then you can use that domain to access your local test web server on your local machine.

For example, I added DNS "A" records for:

  • test.rietta.com -> 127.0.0.1
  • *.test.rietta.com -> 127.0.0.1

Now Rietta's developers can each access his local WEBrick server with:

  • http://test.rietta.com:3000/
  • http://something-made-up-on-the-spot.test.rietta.com:3000/
  • http://something-else.test.rietta.com:3000/
  • etc

Editing your /etc/hosts file is also an option, but that does not support wildcard domains.

Feel free to use my test subdomains if you want.  They will simply point back to your computer.


Wednesday, January 18, 2012

Rails: Gmail Reply-To on Contact Form Email

Most websites have a contact form for visitors to fill out a message that is then e-mailed to the owner or support contact for the website.

When working with a Rails app that will be hosted in a cloud environment that does not supply outbound email delivery it can be convenient to use a Gmail (or Google Apps) account at first for outbound delivery.

The trouble is that Google's SMTP server will rewrite the email address set in the email message to match the address of the account.  You can add verified alias emails to your Gmail account, but obviously you cannot do that for all of your website visitors' addresses.

Suppose your website's account is my_great_rails_app@gmail.com and you do something like the following in your application's mailer:
sender_email_address = "website_user@example.com"
mail( :to => "your_email@example.com",
      :from => sender_email_address,
      :subject => "Message from Your Website")
When you get the message it will be from my_great_rails_app@gmail.com and not from website_user@example.com.  Worse, if you did not think to include a copy of the sender's email in the body of the message you will have no record of who sent it.  That's just not good!

The easiest solution is to set the reply-to header like this:
sender_email_address = "website_user@example.com"
mail( :to => "your_email@example.com",
      :from => sender_email_address,
      :'reply-to' => sender_email_address,
      :subject => "Message from Your Website")
Now the emails from your website will still be from my_great_rails_app@gmail.com, but when you hit reply in your e-mail client your message will be addressed to website_user@example.com.  So you can reply without any extra work.

I hope this helps.

Tuesday, January 17, 2012

Wikipedia *blackout* tomorrow in protest to SOPA/PIPA


Tomorrow (Jan 18) Wikipedia will be shut down for 24 hours in protest of Congress' continuation of consideration of the Stop Online Privacy Act (SOPA) and Protect IP Act (PIPA).

The Wikipedia blackout demonstrates the chilling nature of what can happen when websites can be shutdown on mere accusation without due process.  The new requirements could even stifle early-stage investment in internet startup companies.

According to Sue Gardner, Executive Director of the Wikimedia Foundation:
"The reality is that we don’t think SOPA is going away, and PIPA is still quite active. Moreover, SOPA and PIPA are just indicators of a much broader problem. All around the world, we’re seeing the development of legislation seeking to regulate the Internet in other ways while hurting our online freedoms. Our concern extends beyond SOPA and PIPA: they are just part of the problem. We want the Internet to remain free and open, everywhere, for everyone."
Both the House and Senate bills could be more properly called the legalized authorization of denial of service without due process acts.  Both bills are immensely dangerous to the freedom of speech on the internet.

Please learn as much as you can and write to your representativies in Congress, both in the House and in the Senate.

A good resource is How PIPA and SOPA Violate White House Principles Supporting Free Speech and Innovation.

Saturday, January 14, 2012

Rails: TypeError: nil can't be coerced into Float

When working on Ruby on Rails website some of the common errors that you need to check for is nil objects when something else was expected.  For instance, suppose one of your ActiveRecord models has a price field.  Further suppose that the user left this field blank instead of entering 0.0 as the price.

The computation:
quantity = 3
...
amount_to_charge = price_field * quantity 
Will fail with a "TypeError: nil can't be coerced into Float" exception.  Your user will be shown the dreaded red "We're sorry, but something went wrong" page.
A few observations:
  • This is correct behavior because Ruby as a language cannot assume that a nil object is equivalent to 0.  It will not automatically convert the value to 0 for the purposes of completing the computation.
  • nil implements to_f, which returns 0.0 as a float.
  • nil implements to_i, which returns 0 as an integer.

In the current example, it is reasonable to treat nil as a 0.0.  The following will do that:
quantity = 3
...
amount_to_charge = price_field.to_f * quantity
The same will work with integers using to_i.  Instances when nil can reasonably considered 0 is only something that you, as the programmer can decide.  In most cases it would be better to include good validations and default values in all of your models to avoid this situation altogether.

I hope this helps!

Monday, January 09, 2012

OpenSSL: Encrypt a File with a Password from the Command Line

Do you know how to use OpenSSL to protect sensitive information in storage instead of just in transit across the network?  In fact, your can use the OpenSSL command line too to encrypt a file on your Mac OS X, Linux, or FreeBSD based computer.  Support for the library are included by default in PHP and Ruby.  So there is no reason not to use it to add additional security to your web applications.

Encrypting a File from the Command Line
In terminal, suppose you wanted to encrypt a file with a password (symmetric key encryption).

To do this using the OpenSSL command line tool, you could run this:
openssl aes-128-cbc -in Archive.zip -out Archive.zip.aes128
To decrypt it (notice the addition of the -d flag that triggers a decrypt instead of an encrypt action):
openssl aes-128-cbc -d -in Archive.zip.aes128 -out  Archive.zip
This example uses the Advanced Encryption Standard (AES) cipher in cipher-block chaining mode.  The file is very strongly encrypted for normal purposes assuming that you picked a good passphrase.

According to Bruce Schneier, "...for new applications I suggest that people don't use AES-256. AES-128 provides more than enough security margin for the forseeable future. But if you're already using AES-256, there's no reason to change" (Another New AES Attack, July 30, 2009).

Built into Ruby and PHP
The OpenSSL library is a very standardized open source security library. It's built into the majority of platforms, including Mac OS X, Linux, FreeBSD, iOS, and Android.  Compatible SSL libraries are also built into Java and even the Microsoft platforms.

In future articles, we will explore the usage of OpenSSL for encryption and verification in website projects. In the mean time, check out these API references for both PHP and Ruby.
Impressive Array of Options
On my Mac OS X system, the default openssl install supports and impressive set of 49 algorithms to choose from.
  • aes-128-cbc
  • aes-128-ecb
  • aes-192-cbc
  • aes-192-ecb
  • aes-256-cbc
  • aes-256-ecb
  • base64
  • bf
  • bf-cbc
  • bf-cfb
  • bf-ecb
  • bf-ofb
  • camellia-128-cbc
  • camellia-128-ecb
  • camellia-192-cbc
  • camellia-192-ecb
  • camellia-256-cbc
  • camellia-256-ecb
  • cast
  • cast-cbc
  • cast5-cbc
  • cast5-cfb
  • cast5-ecb
  • cast5-ofb
  • des
  • des-cbc
  • des-cfb
  • des-ecb
  • des-ede
  • des-ede-cbc
  • des-ede-cfb
  • des-ede-ofb
  • des-ede3
  • des-ede3-cbc
  • des-ede3-cfb
  • des-ede3-ofb
  • des-ofb
  • des3
  • desx
  • idea
  • idea-cbc
  • idea-cfb
  • idea-ecb
  • idea-ofb
  • rc2
  • rc2-40-cbc
  • rc2-64-cbc
  • rc2-cbc
  • rc2-cfb
  • rc2-ecb
  • rc2-ofb
  • rc4
  • rc4-40
  • seed
  • seed-cbc
  • seed-cfb
  • seed-ecb
  • seed-ofb
  • zlib
This truly is the swiss army knife of encryption tools.  You should use it too.