Securing Data wtih OpenSSL and Ruby: Part One

Posted by Ben Poweski Thu, 24 Apr 2008 15:53:00 GMT

For the most part Ruby has fantastic APIs. While there is an occasional wart here and there (I”m speaking to you DateTime). In general, it doesn’t suck. The OpenSSL bindings for Ruby are no exception.

Bob, meet Alice

To begin our cultural learnings of OpenSSL and Ruby, let’s take a look at source repository for the interpreter. In the samples directory are some nice examples how the bindings work. It seems that some of the original code examples were never migrated from the RubyPKI project, but thats ok, you can still access them here.

The OpenSSL Digest Class

One of the most common things you’ll most likely need is to create a digest of a string of data. We can do this using by instantiating a Digest class then invoking the hexdigest method.

irb(main):001:0> require 'openssl'
=> true
irb(main):002:0> @sha1 = OpenSSL::Digest::SHA1.new("fooooo")
=> 58c00efa9bed725721b29f4b5f7864f0f191cad5
irb(main):003:0> @sha1.hexdigest
=> "58c00efa9bed725721b29f4b5f7864f0f191cad5"
irb(main):005:0>

Simple enough. But what is the deal with ‘digest’ versus ‘openssl/digest’? According to the ‘digest’ module is only used for backwards compatibility, so use the openssl version when possible.

Available Digest Algorithms

According to the source, the Digest algorithms available are dependent upon the version of OpenSSL compiled with Ruby.

module OpenSSL
  class Digest

    alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
    if OPENSSL_VERSION_NUMBER > 0x00908000
      alg += %w(SHA224 SHA256 SHA384 SHA512)
    end
    ...

Excel Series Decoder in Ruby

Posted by Ben Poweski Wed, 05 Mar 2008 00:16:00 GMT

A co-worker of mine was writing a little script to parse an excel file that contained various network addresses and run various test cases against it. He was stumped on the algorithm how to decoded excel headers to specific indexes. While at first glance this looks like a simple problem, it ended up being more difficult than we thought. My co-worker approached the problem using a procedural approach, this ended up yielding a few nasty loops…far from elegant. The end result ended up being rather easy once the approach was modified to use recursion.

My Solution

require 'test/unit'

def to_excel(i)
  case i
  when 0
    return ''
  when 1..26
    return ('A'..'Z').to_a.at(i - 1)
  else
    q, r = (i - 1).div(26), (i - 1) % 26
    return "#{to_excel(q)}#{to_excel(r + 1)}"
  end
end

class ExcelNumberSeriesTest < Test::Unit::TestCase
  def test_simple
    assert_equal 'A', to_excel(1)
    assert_equal '', to_excel(0)
    assert_equal 'Z', to_excel(26)
  end

  def test_doubles
    assert_equal 'AA', to_excel(27)
    assert_equal 'AB', to_excel(28)
    assert_equal 'AZ', to_excel(52)
  end
end

Compiling Erlang Applications with Rake

Posted by Ben Poweski Fri, 22 Feb 2008 18:05:00 GMT

The irony of Rake is that Ruby really doesn’t need it. This is not to say it isn’t useful to Ruby projects, quite the contrary. Where Rake shines is in building software for applications that require byte code and object code, such as Java or C centric projects.

One such language requiring byte code compilation is Erlang. The design of the runtime environment used by Erlang should be familiar to most Java or C# developers. Erlang uses a byte code compiler (erlc) and various application meta-data files (.app, .rel, .config). For my development work I use Erlide, the Eclipse based Erlang IDE. The standard project layout for an application created in Erlide is:

  • project
    • ebin
    • include
    • src

When creating a Rake file for Erlang projects, I ran into a few problems with compiling the source into the separate ebin directory. Namely, dependencies where not being constructed as desired yielding a full rebuild every time I ran the build script! In the following example I dynamically create the file rules so that the bytecode (.beam) files will only be recompiled if the source (.erl) file is changed.

require 'rake'
require 'rake/clean'

CLEAN.include(['ebin/*.beam', '*.dump'])
SRC = FileList['src/**/*.erl']
BEAM = []

SRC.each do |fn|
  BEAM << dest = File.join('ebin', File.basename(fn).ext('beam'))
  file dest do
    sh "erlc -o ebin #{fn}" 
  end
end

namespace :erlang do
  desc "staring ermail" 
    task :run => [:compile] do
      sh("erl -noshell -pa ebin -s my_mod start")
    end

  desc "run tests" 
  task :test => BEAM do
    sh("erl -noshell -s test_my_mod test -s init stop")
  end
end

task :default => [:compile]
task :start => ['erlang:run']
task :compile => BEAM

Java vs Ruby

Posted by Ben Poweski Fri, 22 Feb 2008 18:04:00 GMT

Forgive me, as this will most likely spark deep seeded hatred from those forced to navigate the deep dark world of Java development. I have managed to break free from it for sometime now, enjoying my Ruby bliss of block passing and metaclasses. Just when I thought I was out, they pull me back in. They, being work. Why can’t we all develop with a language so pointed and terse.

The Java Version

StringBuffer subType = new StringBuffer();
for (String token : tokens) {
  // pretty print the tag
  char[] c = token.replaceAll("flag", "").toCharArray();

  // make first char upper case
  if (c.length > 0)
    c[0] = Character.toUpperCase(c[0]);
  subType.append(c);
}

The Prettier, More Compact, Ruby Version

tokens.collect {|t| t.sub(/flag/, '').capitalize }.join

I can hear the snide remarks right now…save them. There are plenty more examples where that came from.

Deploying Java Applications with Capistrano

Posted by Ben Poweski Fri, 22 Feb 2008 18:01:00 GMT

Capistrano 2, the fantastic sequel to the already superb Rails deployment framework, is an excellent solution to the otherwise mundane task of deploying Java applications.

Network security restrictions prohibit me from using the typically SCM -> Production server configuration. Next, I ran into a few problems uploading Jar files using the put command. Luckily Alex Gorbatchev, posted an example of how to use SFTP within a Capistrano deployment recipe.

I used his idea and adapted my rails recipe using SFTP deployment.

namespace :deploy do                
  task :update_code do
    on_rollback { run "rm -rf #{release_path}" }
    run "mkdir #{release_path}" 
    files = Dir.glob('lib/*.jar') + Dir.glob('dist/*.jar')
    execute_on_servers(options) do |servers|
      servers.each do |server|
        files.each do |path|
          logger.info "uploading #{File.basename(path)} to #{server}"  
          sftp = sessions[server].sftp  
          sftp.connect unless sftp.state == :open  
          sftp.put_file path, File.join(current_path, File.basename(path))  
          logger.debug "done uploading #{File.basename(path)} to #{server}"  
        end
      end
    end    
    finalize_update
  end
end