Permalink
Browse files

+ import of original code by Florian Hanke (floere)

+ Gemspec
+ changed into module Signum
  • Loading branch information...
1 parent a0f18ed commit 252207c71fd5590d32d4e34f0cd33379278b54a2 @jcfischer committed Dec 14, 2010
Showing with 248 additions and 0 deletions.
  1. +2 −0 .bundle/config
  2. +3 −0 .gitignore
  3. +8 −0 Gemfile
  4. +21 −0 Gemfile.lock
  5. +16 −0 README.md
  6. +12 −0 Rakefile
  7. +6 −0 lib/signum.rb
  8. +82 −0 lib/signum/signature.rb
  9. +14 −0 signum.gemspec
  10. +72 −0 spec/signum/signature_spec.rb
  11. +12 −0 spec/spec_helper.rb
View
@@ -0,0 +1,2 @@
+---
+BUNDLE_DISABLE_SHARED_GEMS: "1"
View
@@ -0,0 +1,3 @@
+*.swp
+*.swo
+*.un~
View
@@ -0,0 +1,8 @@
+source :gemcutter
+source 'http://rubygems.org'
+
+gem 'rake'
+
+group :test do
+ gem 'rspec', '~> 2.3.0'
+end
View
@@ -0,0 +1,21 @@
+GEM
+ remote: http://rubygems.org/
+ remote: http://rubygems.org/
+ specs:
+ diff-lcs (1.1.2)
+ rake (0.8.7)
+ rspec (2.3.0)
+ rspec-core (~> 2.3.0)
+ rspec-expectations (~> 2.3.0)
+ rspec-mocks (~> 2.3.0)
+ rspec-core (2.3.0)
+ rspec-expectations (2.3.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.3.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ rake
+ rspec (~> 2.3.0)
View
@@ -0,0 +1,16 @@
+Signum
+======
+
+A library to compute cryptographic signatures of strings. We use it protect
+parameters passed to an API by signing the params, and passing that signature
+along. On the receiving side, the params are checked against the signature to
+detect spoofing. Of course this needs some kind of secret to prevent a slightly
+higher skilled hacker to just re-compute the signature.
+
+Installation
+------------
+
+Usage
+-----
+
+
View
@@ -0,0 +1,12 @@
+require 'rake'
+
+require 'rspec'
+require 'rspec/core/rake_task'
+
+spec_root = File.join File.dirname(__FILE__), 'spec'
+
+desc "Run specs"
+RSpec::Core::RakeTask.new :spec
+
+task :default => :spec
+
View
@@ -0,0 +1,6 @@
+require File.expand_path '../signum/signature', __FILE__
+
+module Signum
+
+
+end
View
@@ -0,0 +1,82 @@
+module Signum
+
+class Signature
+
+ attr_reader :signature
+
+ def initialize signature
+ @signature = signature
+ end
+
+ # Use this method to create a signature from params.
+ #
+ def self.for secret, params
+ cleaned = clean params
+ signature = generate_signature prepared(cleaned), secret
+
+ new signature
+ end
+
+ # Blacklists controller & action.
+ #
+ # Returns a copy.
+ #
+ def self.clean params
+ params = params.dup
+ params.delete :controller
+ params.delete 'controller'
+ params.delete :action
+ params.delete 'action'
+ params
+ end
+
+ #
+ #
+ def == other
+ puts "self : #{self.signature.inspect}"
+ puts "other: #{other.signature.inspect}"
+ self.signature == other.signature
+ end
+
+ #
+ #
+ def <=> other
+ self.signature <=> other.signature
+ end
+
+ #
+ #
+ def self.prepared params
+ stringified normalize(params)
+ end
+
+ # Normalize the params. This means currently:
+ # * Stringify the amount.
+ #
+ def self.normalize params
+ params['amount'] &&= sprintf "%.2f", params['amount']
+ params
+ end
+
+ # Sort and stringify the incoming params
+ #
+ def self.stringified params
+ sorted_params = params.to_a.sort
+ s = sorted_params.map { |key, value| "#{key.to_s}:#{value.to_s}" }.join(",")
+ puts s
+ s
+ end
+
+ # Generate a signature for the given params.
+ #
+ def self.generate_signature from_string, secret
+ Digest::MD5.hexdigest(from_string + secret)
+ end
+
+ def to_s
+ signature
+ end
+
+end
+
+end
View
@@ -0,0 +1,14 @@
+Gem::Specification.new do |s|
+ s.name = 'signum'
+ s.version = '0.0.1'
+ s.authors = ['Florian Hanke', 'Jens-Christian Fischer']
+ s.email = 'jens-christian@invisible.ch'
+ s.homepage = 'http://github.com/jcfischer/signum'
+ s.platform = Gem::Platform::RUBY
+ s.summary = "Library to create and compare signatures of parameter hashes"
+ s.description = 'Sign and compare signatures of parameters passed to a web application.'
+ s.files = Dir["lib/**/*.rb"]
+ s.test_files = Dir["spec/**/*spec.rb"]
+ s.has_rdoc = false
+ s.extra_rdoc_files = ['README.md']
+end
@@ -0,0 +1,72 @@
+require 'spec_helper'
+
+describe Signum::Signature do
+
+ describe "==" do
+ it "should return the right value" do
+ Signum::Signature.new('bla').==(Signum::Signature.new('bla')).should == true
+ end
+ it "should return the right value" do
+ Signum::Signature.new('bla').==(Signum::Signature.new('hulubulu')).should == false
+ end
+ end
+
+ describe "clean" do
+ it "should clean some keys" do
+ Signum::Signature.clean( :a => :b, :controller => :some_controller, :action => :some_action ).should == { :a => :b }
+ end
+ end
+
+ describe "Signum::Signature.for" do
+ it "should generate the right signature" do
+ expected = Signum::Signature.generate_signature 'amount:a,api_key:b,merchant_id:c', 'secret'
+ actual = Signum::Signature.for 'secret', :merchant_id => 'c', :api_key => 'b', :amount => 'a'
+
+ actual.signature.should == expected
+ end
+ it "should generate the right signature even if there is action & controller" do
+ expected = Signum::Signature.generate_signature 'amount:a,api_key:b,merchant_id:c', 'secret'
+ actual = Signum::Signature.for 'secret', :merchant_id => 'c', :api_key => 'b', :amount => 'a', :controller => 'some/controller', :action => 'some_action'
+
+ actual.signature.should == expected
+ end
+ end
+
+ describe "Signum::Signature.normalize" do
+ it "needs a correct amount to function" do
+ Signum::Signature.normalize( 'amount' => nil ).should == { 'amount' => nil }
+ end
+ it "should normalize the amount" do
+ Signum::Signature.normalize( 'no_amount' => 'sorry' ).should == { 'no_amount' => 'sorry' }
+ end
+ it "should normalize the amount" do
+ Signum::Signature.normalize( 'amount' => 1.23456789 ).should == { 'amount' => '1.23' }
+ end
+ it "should normalize the amount" do
+ Signum::Signature.normalize( 'amount' => 14 ).should == { 'amount' => '14.00' }
+ end
+ it "should normalize the amount" do
+ Signum::Signature.normalize( 'amount' => 22.50 ).should == { 'amount' => '22.50' }
+ end
+ it "should normalize the amount" do
+ Signum::Signature.normalize( 'amount' => 0.55 ).should == { 'amount' => '0.55' }
+ end
+ it "should normalize the amount" do
+ Signum::Signature.normalize( 'amount' => 1000.00 ).should == { 'amount' => '1000.00' }
+ end
+ end
+
+ describe "Signum::Signature.generate_signature" do
+ it "should generate a correct signature" do
+ Signum::Signature.generate_signature('firstsecond', 'third').should == '272bfa314ea293c357dd9f45ba979a16'
+ end
+ end
+
+ describe "Signum::Signature.stringified" do
+ it "stringify the params correctly" do
+ Signum::Signature.stringified(:z => :third, :c => :second, :a => :first).should == 'a:first,c:second,z:third'
+ end
+ end
+
+end
+
View
@@ -0,0 +1,12 @@
+begin
+ require 'bundler'
+rescue LoadError => e
+ require 'rubygems'
+ require 'bundler'
+end
+Bundler.setup :test
+Bundler.require
+
+require File.expand_path '../../lib/Signum', __FILE__
+
+

0 comments on commit 252207c

Please sign in to comment.