Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Lazy Ruby Cryptography

What is Cryptography?

Cryptography is the art of making clear text illegible by anyone but the original recipients. It is an art that is at least as old as the Roman Repulic, when Julius Caesar used the Caesar cipher to encrypt orders to his centurions in the Gallic wars.

Since then, cryptography has evolved into a science unto itself, which helped kickstart computer science (and thus programming) during World War 2.

I encourage you to discover the history of cryptography. It makes for a good techno-thriller with lots of cloak-and-dagger.

The Two Areas of Cryptography

Cryptogrpahic algorithms are used in two main areas: Validation and encryption. Validation algorithms, or message/hash digests, provide a means to verify that data has not been modified somehow. A rather mundane use of this verification is testing the hash finger print of a file after a download to make sure that the file wasn’t corrupted during the transfer.

Encryption and decryption are used to prevent a third party from reading the message. Online banking or e-commerce websites use this to secure the communication between your browser and their servers when you send payment details.

Get It

You don’t have to install anything, since Ruby includes OpenSSL bindings.

Using Hashes

Important Upfront Note

Unless you have to deal with already existing data, do not use MD5. It is considered broken.

Hashing Data

Consider the following snippet:

require 'digest/sha2'  sha256 = Digest::SHA2.new(256)  sha256.digest("data to be hashed")

After requiring the SHA2 hashing algorithm, we first have to initialize an SHA2 oject with the desired key-length (Ruby supports both 256 and 512 bit keys), before we can digest data.

The key length is important:

sha2_256 = Digest::SHA2.new(256)  sha2_512 = Digest::SHA2.new(512)  sha512_hashed = sha2_512.digest("super secret password")  sha256_hashed = sha2_256.digest("super secret password")  puts sha256_hashed == sha512_hashed

If you run this, you will see “false”. This is obvious enough, since the keylength is different, but it is a gotcha. Make sure you know what algorithm was used to hash the data, otherwise you’ll get false negatives.

The MD5 and SHA1 digests work similarly, but you don’t have to instantiate a new object:

require 'digest/md5' require 'digest/sha1'  Digest::MD5.digest("super secret password") Digest::SHA1.digest("super secret password")

Symmetric Cryptography with AES

Symmetric cryptography, or symmetric-key cryptography means that data is encrypted and decrypted with the same key. That has the benefit that it is much easier to work with, but also means that both the encrypted data and the key used to encrypt this data has to be exchanged somehow. Pulic/Private key (or asymmetrical) cryptography avoids this problem: One key is used to encrypt data, another is used to decrypt data (however, it is theoretically possible to derive one key from another, but there are no known, working attacks of this sort).

Public/Private key encryption deserves its own tutorial, so we will only deal with symmetric cryptography this time.

Let us look at some source code, where we encrypt, and then immediately decrypt clear text:

require 'openssl'  aes = OpenSSL::Cipher.new("AES-256-ECB")  key = sha2_256.digest("super secret password")  aes.encrypt aes.key = key  payload = aes.update("A very secret message.") + aes.final  puts payload  aes.reset  aes.decrypt aes.key = key  puts aes.update(payload) + aes.final

This looks more complex than it really is.

First, we load the OpenSSL bidings, which Ruby uses to do encryption.

Then, we instantiate a new AES cipher object. If you want to know which algorithms Ruy supports, OpenSSL::Cipher.ciphers will tell you.

Now that we have an AES object, we need a key to encrypt data. AES-256 expects an encryption key that is at least 256 bits long (the key size is determined by which AES variant you use). To achieve that, and to make the key harder to guess, we hash a passphrase with SHA2-256.

The next step is to call the encrypt method. That initializes the cryptographical systems needed (like acquiring a source of entropy). Both the decrypt and the encrypt method must be called before any other method!

Finally, we encrypt our data by calling

payload = aes.update("A very secret message.") + aes.final

The important part of this is the aes.final call. This adds the last block of encrypted data to our payload variable plus any necessary padding for AES, which is determined by the algorithm’s block size—the block size are 128 bit chunks of data that each get encrypted, more or less.

To decrypt the data, we reset our AES object, and call decrypt on it. The decryption process works analogous to the encryption. It is symmetric, if you allow me such a lazy pun.

Enhanced Security

If you use the same key to encrypt data several times, you are suverting the security that encryption provides. Sooner or later, parts of the message will repeat themselves and look the same even when encrypted (this is one of the vectors that were used in Bletchley Park by Alan Turing et al to break the Kriegsmarine Enigma system).

Thus, almost all modern ciphers have an Initialization Vector or IV (link is in the Resources section). Ruby cipher ojects have the iv method, which allows you to feed an IV into your cryptography. Make sure that the IV source is random (like Ruby’s rand method), and does not repeat itself.

Do Not Use DES

The DES algorithm has been broken (link below).

Resources

Footnotes

Lazy PDF creation with Prawn: A Tutorial In One Part

What is Prawn?

Prawn is a pure Ruby library to generate PDFs. It takes much of the pain away (though, using a publishing tool like Scribus or Adobe InDesign CS5.5 make a more visual approach much easier. However, to create PDFs on the fly, Prawn is the most convenient tool you can find.

Get It

gem install prawn

Use It

require 'prawn'

Creating PDFs

No matter what the PDF shall contain, you will always use the Prawn::Document.generate method. I prefer the block invocation:

Prawn::Document.generate "example.pdf" do end

Sample Content

I want to show off as many of Prawn’s features, so I’ve prepared some sample data:

# Our headings  heading = "The Traditional Filler Content"  sub_heading = "It Has No Inherent Meaning"  # Our body body = <<-EOS Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quisnostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.  EOS  formatted = "<b>Inline</b> <i>formatting</i> is a <strikethrough>useless<strikethrough> <u>useful</u> feature!"

Simple Text And Inline Formatting

PDF is, first and foremost, a text format. Everything else is just sugar (or a liability, as the case may be). Since an introduction to everything Prawn (and PDFs) have to offer would be far from a Lazy Tutorial, we will deal with outputting text as PDF.

Simple Text…

Let’s take our sample text, and create a PDF with a large heading, a smaller sub-heading, and a creation date as cover page, and let’s fill the PDF with a bit of dummy text:

Prawn::Document.generate "example.pdf" do text heading, :align => :center, :size => 48  text sub_heading, :align => :center, :size => 32  text "\nCreated on #{Time.now}\n", :align => :center  start_new_page  10.times do group do text body end end end

As you have already guessed, the text method takes text, and outputs it to the PDF, and it takes the :align and the size arguments. If you look at the freshly created PDF, the headings are larger than the creation date, and all of them are aligned in the center of the document.

start_new_page does exactly what it says on the tin, and starts a new page. text body outputs the text we’ve assigned to the variable. And you will have noticed the group do…end block. This tells prawn to keep the stuff enclosed with group do…end as a group, and, if possible, keep them on the same page. Otherwise, the paragraph would overflow.

…And Inline Formatting

I have hinted at it quite a bit, so it won’t be surprising you when I say that Prawn allows for inline formatting, with the help of the tiniest HTML syntax subset: , , , and are supported. However, Prawn will not automatically parse HTML for you. Instead you have to manually invoke the feature:

Prawn::Document.generate "example.pdf" do # ...  font_size 12 do text formatted, :inline_format => true end end

It’s as simple as that. Just so that it looks like I did some work, I’ve also used the font_size size do…end, which does what it says on the tin for everything that’s within the block.

Custom Fonts

One of the strengths of the PDF format is typography: Preserving the typeface of the text you added. Since not every document is (or can be) limited to the “built in” fonts—see Standard Type 1 Fonts for details which are defined, Prawn lets you define custom font_families:

font_families["Nobile"] = { :normal => "./nobile.ttf", :bold => "./nobile_bold.ttf", :bold_italic => "./nobile_bold_italic.ttf", :italic => "./nobile_italic.ttf" }  text formatted, :inline_format => true, :font => "Nobile"

For typographical / dead tree print reasons, it is expected that you define font faces for bold, italic (or cursive), and italicized bold weights. With font my_font you can assign this font for everything that follows. If you want to limit the font directive, you can use the block form, or a :font => my_font hash.

Pagination and Page Numbering

Few documents are exactly one page long, so it’s no surprise that Prawn offers page numbering:

number_pages "Page  of  pages", :at => [bounds.right - 100,0], :page_filter => :all

Simple enough. :at determines where the numbering is printed, and page_filter determines on which page (:all, :odd, or :even).

Resources

Story Telling

To provide an application that does what the user wants and does what the user wants, we need, obviously enough, requirements and maybe even a specification (depending on where and how the application gets deployed, if legal requirements have to be figured in, or high availability has to be guaranteed, for example).

For the scope of this project (quick recap: Document management), requirements are enough.

Now, we have to capture these requirements in a way that our client (who isn't necessarily tech-savvy) understands, and that allows us, the developers, to know exactly what has to be done to fulfill the user's needs.

That means we have to use a language that both sides understand and that is free from ambiguities.

Both vanilla English or your native language as well as a programming language are ill suited to this task: Spoken languages are filled with ambiguities, and programming languages are not necessarily understood by the client.

What we need is something that is non-ambiguous, but easily understood.

The solution is rather obvious: An English (or your native language) with limited vocabulary, that can be intuitively understood and has only a few rules, internalized quickly.

For that, we should look at what Extreme Programming has to offer: User stories.

And we can take this to the extreme (so to speak, and pardon the pun) in the Ruby world with RSpec, a BDD testing framework. In the next few posts I'll take a look at RSpec and BDD, and share my thoughts and examples (bear with me: I'm taking a serious look at BDD/RSpec for the first time, myself).

I am lazy. That's why I like J2EE

No, really. Without J2EE, I wouldn't have access to Glassfish, with its wonderful autodeploy directory to, well, autmatically delpoy applications on it.

Without Java, I wouldn't be able to use JRuby.

And neither would I be able to use Warbler to create .war-files for drag and drop deployment.

In the span of 30 minutes (half of which is related to my underspec'd development environment), I was able to deploy a Rails application.

First, you need to setup your Rails application for use with JDBC. In Rails 2.0 it is as easy as this database.yml:

development:
host: localhost
adapter: jdbc
driver: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/application_db
username:
password:
With the Warbler gem, you can easily create a war file:
jruby -S warble war
To fine-tune your configuration (if Warble's defaults aren't as good for you as they could), just run
jruby -S warble config
You can edit the resulting config\warble.rb for some fine tuning (I'll have to look into it, for example how to tell it to use a specific JRuby version).

Once you are ready to create your .war-file:
jruby -S rake war:standalone:create
Thsi creates a war file inculding the JRuby runtime. Drop into your domain's autodeploy folder, and wait until Glassfish is done deploying it. Done. You have a working, deployed, and automagically scaling Rails application. No need to herd a pack of Mongrels, futy with mod_proxy, or anything else. Wonderful.

BUT there is one issue you migth have (whcih is unrelated to Ruby, JRuby, or Glassfish):

It is possible that your Rails app throws the following exception:
No :secret given to the #protect_from_forgery call. Set that or use a session store capable of generating its own keys (Cookie Session Store).
Don't fret. Either use the correct security, or change your app/controllers/application.rb so it looks like this:
protect_from_forgery :secret => 'a_really_long_pseudo_random_hash_thing'

Simply remove the comment in front of the :secret. Done. Enjoy the bonus you just ensured for yourself, since you avoided at least a day of additional deployment and configuration, and/or learning capistrano.

P.S.: Still working on the comparison of OpenID and CAS for Ruby, so this is a bit of filler content.

Wide OpenID. SSO for the user.

OpenID. Doesn't that sound wonderful? It is open. Right there in the name it says that it is! And it is about IDs, too! Er, wait. What is it?

OpenID is an open standard that is not vendor controlled. That is, neither Google, nor Microsoft, nor Apple could change the nature of the standard and 'neglect' to tell everybody about it.

The aim of OpenID is to provide users with a means to log in at websites without creating an account with a specific site (if you run your own OpenID server, you don't have to tell anybody your username/password).

After this little overview of OpenID, let's get into Ruby-OpenID:

Like Ruby-CAS, this package comes in two flavors: A server component, and a client component.


My own OpenID server? Anyone? Bueller? Bueller?

However, compared to Ruby-CAS, the server component is limited. The OpenID server (based on Rails) is an example only, and doesn't even come with tests to take a look at how it works. A shame, really. So, without this, you'll have to roll your own solution to this. Since this is a Ruby gem, you can easily create a server and roll with it, using any storage solution you chose. However, the investment on your part is much higher than with Ruby-CAS' server, which provides a turn-key solution, unless you need something that is very uncommon (like me ;).

My client has OpenID. He showed me the URL.

The client side is a bit more complex. For login, users have to provide an OpenID enabled URL, from one of the many OpenID providers. Chances are, that you already have an OpenID URL, without knowing it (off the top of my head, Blogger, Yahoo!, LiveJournal, and AOL provide OpenID URLs already)!

With this URL, a web application can authenticate a user. You get redirected to the provider (discovered via the Yadis protocol, to standardize the data protocol. Isn't interoperability fun?), and have to provide your credentials there, and then you have to approve the application (just once, or permanently), too. Or rather, the application's URL. And you have to repeat this process for every single account you create someplace else. After approving the URL, you get redirected back to the site that requested your authentication, and you are being logged into the app (or an account is created for you, and then you are logged in, or however this is handled).

This solution is ideal for the internet (where services rarely know about each other), but not so good for an intranet (where services and people know about each other).

Ceterum censeo Carthaginem esse delendam

If you want to create trust, without forcing people to create accounts and maintain yet another set of username/passwords/mock-two-factor-authentication-security-question, OpenID is certainly the way to go. Even to create accounts for your web service's users.

The big downside is, that proxy-authentication (like with CAS) isn't possible, or you have to roll your own, somehow.

Also, since OpenID is pretty much roll your own on the server side, other solutions are probably better for you if you want to have SSO for an intranet.

If you want to read more about Ruby-CAS, I wrote an entry about that, too.

Coming soon: Oh my God, what did I get myself into this time? Or: Comparing Ruby-CAS and Ruby-OpenID.

A case for CAS

A couple of days ago, I talked about the limited options of SSO on the Ruby side of things. This turned out to be a bit of a mistake. In fact, the two viable SSO solutions are viable, and feature rich, providing what you need on the authentication server's side, as well as the client's side.

The issue was more that there are only these two options in the first place.

However, I'm going to take a deeper look at these two options. I'll do this in three articles, focusing on RubyCAS client and server first, OpenID client and server second, and comparing these against each other in the last episode.

Now, without further ado, a look into CAS.

CAS is Yale's solution to the SSO problem. It provides a client/server architecture, allowing each application to authenticate users against a single server.

Matt Zukowski (his RubyForge profile) implemented the Ruby variants of the Central Authentication Service Protocol (short CAS), both on the server side (RubyCAS server), and the client side (RubyCAS client).

Clientèle dealings

The client simply enables to authenticate against a server implementing the CAS protocol. That's it. Well, not quite.

Actually, a CAS enabled website hands authentication off to the CAS server login page, which checks the user's credentials, and redirects back to the requested webpage on successful authentication. The web application verifies that the user has, indeed, logged in, and works as expected.

The benefit of CAS for web-based SSO is, that any CAS-enabled application can use the ticket issued by the CAS server for authentication, as long as the server can read the cookie placed (so, it has to be the same URI that reads the cookie, not necessarily the same server).

Serving the greater good

The server works a bit different, and necessarily so. It takes the user's credentials, authenticates the user against the configured form of storage, and redirects back to the application requesting the authentication of the user.

For authentication, RubyCAS server brings three pre-configured Authenticators:

  • CASServer::Authenticators::LDAP to authenticate against an LDAP directory service, and LDAP's cousin Active Directory gets its own Authenticator, called.
  • Additionally, there is an SQL authenticator CASServer::Authenticators::SQL, which can use any SQL database that ActiveRecord can talk to.
  • If none of these fit the bill, you can apparently use CASServer::Authenticators::Base to roll your own authenticator (the RDoc documentation is rather silent on the issue, and I haven't dug into the source code yet).

Concluding the obvious

As long as you use Ruby, you should be able to use RubyCAS client (you'll probably have to do some source code hacking if you don't use ActiveRecord for the RubyCAS server, though).

This should be of a great boon in any organization using the CAS system already. And the wealth of client options provided by the CAS ecosystem should make CAS an easy sell if you are looking for an SSO solution.

Kicking off the blog (and the project, too)

I promised myself, that I'd chronicle my efforts in developing a project from start to finish.

Well, this won't quite work out, since I already have the contract in hand. ;)

However, I'll write up what I am going to do, what I am doing, and the milestones reached. Well, a software development blog.


So, what's the project about?

I have to build a web-based Document management system.

Requested Features:

  • Single Sign On
  • Import documents from a network share
  • Storage of metadata (an odd one in this case is, that physical locations have to be recorded, too, in case the government agency sending it cannot deal with electronic documents. Legal requirements are fun like that)
  • Fortunately, no detailed tracking for SOX or other such regulations.

What's coming up

At first, I'll post progress about gathering requirements, proposals and recommendations of solutions for these requirements that go out to the client (after I've sent them, though).

After that, I'll report my progress with the application: What I did, why I did it, and what the challenges were.

And last but not least, I'll talk about the deployment of the application, and its maintenance.

So, what are you using?

The web application framework is going to be Ruby on Rails, the database back-end MySQL, the webserver will be Apache of some sort. What'll serve the Rails pages I don't know yet. Maybe Glassfish with JRuby, maybe mod_rails, possibly the classic Apache + Pack of Mongrels solution. We'll see when I get there.

My development OS will be Windows XP together with a Debian VM and a Kubuntu 8.04 installation as primary development OS.

The deployment will be on FreeBSD 5.4 (I know, I can't influence that, and neither can my client).

The approach I'll be using, even though I'm just one person, is a simple variant of Agile Development: Sprints, and loads of tests before I write the actual code.