lib/enigma.rb in enigma-0.0.1 vs lib/enigma.rb in enigma-0.0.3
- old
+ new
@@ -1,123 +1,90 @@
-$:.unshift(File.dirname(__FILE__)) unless
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
-
require 'rubygems'
-require 'cgi'
-require 'yaml'
-require 'rest_client'
-require 'addressable/uri'
-require "digest/sha1"
-require 'ezcrypto'
+require 'bundler/setup'
+require 'rack'
+require 'rack/test'
module Enigma
- VERSION = '0.0.1'
+ SIGNATURE_HEADER = "X_ENIGMA_SIGNATURE"
- KEY_LENGTH = 32
- SECRET_LENGTH = 32
+ extend self
+ def self.server_key=(server_key)
+ @server_key = server_key
+ end
- class Query < Hash
+ def self.server_key
+ @server_key
+ end
- def initialize(key, secret, params)
- self[:key] = key
- self[:params] = Enigma.encode_params(secret, params)
- end
+ def signature(method, path, payload)
+ message = [method, path, payload].map(&:to_s).inject(&:+)
- def to_params
- params = ''
- stack = []
-
- each do |k, v|
- if v.is_a?(Hash)
- stack << [k,v]
- else
- params << "#{k}=#{v}&"
- end
- end
-
- stack.each do |parent, hash|
- hash.each do |k, v|
- if v.is_a?(Hash)
- stack << ["#{parent}[#{k}]", v]
- else
- params << "#{parent}[#{k}]=#{v}&"
- end
- end
- end
-
- params.chop! # trailing &
- params
- end
+ digest = OpenSSL::Digest::Digest.new("sha512")
+ OpenSSL::HMAC.hexdigest(digest, self.server_key, message).to_s
end
- class KeyGenerator
- def self.generate(length = 10)
- Digest::SHA1.hexdigest(Time.now.to_s + rand(12341234).to_s)[1..length]
+ def matches?(actual_signature, method, path, payload)
+ matched = true
+ expected_signature = self.signature(method, path, payload)
+ expected_signature.each_char.zip(actual_signature.to_s.each_char).each do |expected, actual|
+ matched = false if expected != actual
end
- end
- def self.generate_key
- KeyGenerator.generate(KEY_LENGTH)
+ matched
end
- def self.generate_secret
- KeyGenerator.generate(SECRET_LENGTH)
- end
+ class Client
+ def initialize(options)
+ @host = options[:host] || 'localhost'
+ @port = options[:port] || 80
+ @ssl = options[:ssl] || false
+ @certificate = options[:certificate]
+ end
- def self.find_secret(&block)
- @find_secret = block
- end
+ attr_reader :host, :port, :ssl, :certificate, :version
- def self.authenticate(params={})
- if @find_secret.nil?
- raise "Pass a block to #{self.name}.find_secret which returns
- secret for the given key. See documentation for details."
- end
+ HTTP_METHODS = [:get, :post, :put, :delete]
+ HTTP_METHODS.each do |method|
+ define_method(method) do |path, *args|
+ payload = args.first
+ execute method, path, payload
+ end
+ end
- self.decode_params(@find_secret.call(params[:key]), params[:params])
- end
+ def http
+ base = "#{ssl ? "https" : "http"}://#{host}:#{port}"
+ Class.new do
+ include HTTParty
+ base_uri base
+ end
+ end
- def self.encrypt(secret, data)
- key = EzCrypto::Key.with_password(secret, "salt")
- key.encrypt(data)
- end
+ def execute(method, path, payload)
+ response = http.send(method, path,
+ :headers => headers(method, path, payload),
+ :body => payload,
+ :timeout => TIMEOUT
+ )
- def self.decrypt(secret, data)
- key = EzCrypto::Key.with_password(secret, "salt")
- key.decrypt(data)
- end
+ response.body
+ end
- def self.encode_params(secret, params)
- CGI::escape(
- encrypt(
- secret, [ YAML::dump(params.sort {|a,b| a[0].to_s <=> b[0].to_s}) ].
- pack('m')
- )
- )
- end
+ TIMEOUT = 60 * 5
- def self.decode_params(secret, signed_params)
- begin
- params = {}
- YAML::load(decrypt(secret, CGI::unescape(signed_params)).unpack('m').first).each do |key, value|
- params[key] = value
- end
- return params
- rescue
- return nil
- end
- end
+ private
- class Client
- def initialize(key, secret)
- @key = key
- @secret = secret
- end
+ def headers(method, url, payload)
+ {Enigma::SIGNATURE_HEADER =>
+ Enigma.signature(method, url, payload)
+ }
+ end
- def get(url, params={})
- query = Query.new(@key, @secret, params)
- RestClient.get("#{url}?#{query.to_params}")
- end
- end
+ def scheme
+ @ssl ? 'https' : 'http'
+ end
+ def base_url
+ "#{scheme}://#{host}:#{port}"
+ end
+ end
end