enigma 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ === 0.0.1 2010-04-02
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,13 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ lib/enigma.rb
7
+ script/console
8
+ script/destroy
9
+ script/generate
10
+ spec/enigma_spec.rb
11
+ spec/spec.opts
12
+ spec/spec_helper.rb
13
+ tasks/rspec.rake
@@ -0,0 +1,7 @@
1
+
2
+ For more information on enigma, see http://enigma.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
@@ -0,0 +1,97 @@
1
+ = enigma
2
+
3
+ * http://github.com/teejayvanslyke/enigma
4
+
5
+ == DESCRIPTION:
6
+
7
+ Key/secret authentication for your web services
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * I just started implementing this today, so it's really not ready for use. I
12
+ would love your opinions about the current API and possible improvements.
13
+
14
+ == SYNOPSIS:
15
+
16
+ Let's say you have a web service endpoint coded in Sinatra that says "Hello,
17
+ world":
18
+
19
+ # app.rb
20
+ get '/' do
21
+ "Hello, world!"
22
+ end
23
+
24
+ Enigma will allow you to authenticate the service using a key/secret scheme:
25
+
26
+ >> Enigma.generate_key
27
+ => "03637dee19a1c96c1547f8834ca5e96c"
28
+ >> Enigma.generate_secret
29
+ => "1f430a0481601697898a566ae54fde5a"
30
+
31
+ # app.rb
32
+
33
+ Enigma.find_secret do |key|
34
+ # Usually, you'd have these stored in your database.
35
+ # For this example, we'll just return the secret if we have a matching
36
+ # key.
37
+ if key == "03637dee19a1c96c1547f8834ca5e96c"
38
+ return "1f430a0481601697898a566ae54fde5a"
39
+ end
40
+ end
41
+
42
+ get '/' do
43
+ if (params = Enigma.authenticate(params))
44
+ "Hello, world."
45
+ else
46
+ "Not authorized."
47
+ end
48
+ end
49
+
50
+ It provides a wrapper for the rest-client gem which properly encodes URI
51
+ parameters on the query string for consumption by Enigma:
52
+
53
+ # client.rb
54
+
55
+ client = Enigma::Client.new(
56
+ "03637dee19a1c96c1547f8834ca5e96c",
57
+ "1f430a0481601697898a566ae54fde5a"
58
+ )
59
+
60
+ client.get("http://localhost:4567").body
61
+ => "Hello, world."
62
+
63
+ The Enigma.authenticate method returns the unencoded parameters if the
64
+ authentication is successful; otherwise it returns nil.
65
+
66
+ == REQUIREMENTS:
67
+
68
+ * ezcrypto
69
+
70
+ == INSTALL:
71
+
72
+ sudo gem install enigma
73
+
74
+ == LICENSE:
75
+
76
+ (The MIT License)
77
+
78
+ Copyright (c) 2010 FIXME full name
79
+
80
+ Permission is hereby granted, free of charge, to any person obtaining
81
+ a copy of this software and associated documentation files (the
82
+ 'Software'), to deal in the Software without restriction, including
83
+ without limitation the rights to use, copy, modify, merge, publish,
84
+ distribute, sublicense, and/or sell copies of the Software, and to
85
+ permit persons to whom the Software is furnished to do so, subject to
86
+ the following conditions:
87
+
88
+ The above copyright notice and this permission notice shall be
89
+ included in all copies or substantial portions of the Software.
90
+
91
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
92
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
93
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
94
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
95
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
96
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
97
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/enigma'
6
+
7
+ Hoe.plugin :newgem
8
+ # Hoe.plugin :website
9
+ # Hoe.plugin :cucumberfeatures
10
+
11
+ # Generate all the Rake tasks
12
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
13
+ $hoe = Hoe.spec 'enigma' do
14
+ self.developer 'T.J. VanSlyke', 'teejay.vanslyke@gmail.com'
15
+ self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
16
+ self.rubyforge_name = self.name # TODO this is default value
17
+ self.extra_deps = [['ezcrypto', '>= 0.7.2']]
18
+
19
+ end
20
+
21
+ require 'newgem/tasks'
22
+ Dir['tasks/**/*.rake'].each { |t| load t }
23
+
24
+ # TODO - want other tests/tasks run by default? Add them to the list
25
+ # remove_task :default
26
+ # task :default => [:spec, :features]
@@ -0,0 +1,123 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ require 'cgi'
6
+ require 'yaml'
7
+ require 'rest_client'
8
+ require 'addressable/uri'
9
+ require "digest/sha1"
10
+ require 'ezcrypto'
11
+
12
+ module Enigma
13
+ VERSION = '0.0.1'
14
+
15
+ KEY_LENGTH = 32
16
+ SECRET_LENGTH = 32
17
+
18
+
19
+ class Query < Hash
20
+
21
+ def initialize(key, secret, params)
22
+ self[:key] = key
23
+ self[:params] = Enigma.encode_params(secret, params)
24
+ end
25
+
26
+ def to_params
27
+ params = ''
28
+ stack = []
29
+
30
+ each do |k, v|
31
+ if v.is_a?(Hash)
32
+ stack << [k,v]
33
+ else
34
+ params << "#{k}=#{v}&"
35
+ end
36
+ end
37
+
38
+ stack.each do |parent, hash|
39
+ hash.each do |k, v|
40
+ if v.is_a?(Hash)
41
+ stack << ["#{parent}[#{k}]", v]
42
+ else
43
+ params << "#{parent}[#{k}]=#{v}&"
44
+ end
45
+ end
46
+ end
47
+
48
+ params.chop! # trailing &
49
+ params
50
+ end
51
+ end
52
+
53
+ class KeyGenerator
54
+ def self.generate(length = 10)
55
+ Digest::SHA1.hexdigest(Time.now.to_s + rand(12341234).to_s)[1..length]
56
+ end
57
+ end
58
+
59
+ def self.generate_key
60
+ KeyGenerator.generate(KEY_LENGTH)
61
+ end
62
+
63
+ def self.generate_secret
64
+ KeyGenerator.generate(SECRET_LENGTH)
65
+ end
66
+
67
+ def self.find_secret(&block)
68
+ @find_secret = block
69
+ end
70
+
71
+ def self.authenticate(params={})
72
+ if @find_secret.nil?
73
+ raise "Pass a block to #{self.name}.find_secret which returns
74
+ secret for the given key. See documentation for details."
75
+ end
76
+
77
+ self.decode_params(@find_secret.call(params[:key]), params[:params])
78
+ end
79
+
80
+ def self.encrypt(secret, data)
81
+ key = EzCrypto::Key.with_password(secret, "salt")
82
+ key.encrypt(data)
83
+ end
84
+
85
+ def self.decrypt(secret, data)
86
+ key = EzCrypto::Key.with_password(secret, "salt")
87
+ key.decrypt(data)
88
+ end
89
+
90
+ def self.encode_params(secret, params)
91
+ CGI::escape(
92
+ encrypt(
93
+ secret, [ YAML::dump(params.sort {|a,b| a[0].to_s <=> b[0].to_s}) ].
94
+ pack('m')
95
+ )
96
+ )
97
+ end
98
+
99
+ def self.decode_params(secret, signed_params)
100
+ begin
101
+ params = {}
102
+ YAML::load(decrypt(secret, CGI::unescape(signed_params)).unpack('m').first).each do |key, value|
103
+ params[key] = value
104
+ end
105
+ return params
106
+ rescue
107
+ return nil
108
+ end
109
+ end
110
+
111
+ class Client
112
+ def initialize(key, secret)
113
+ @key = key
114
+ @secret = secret
115
+ end
116
+
117
+ def get(url, params={})
118
+ query = Query.new(@key, @secret, params)
119
+ RestClient.get("#{url}?#{query.to_params}")
120
+ end
121
+ end
122
+
123
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/enigma.rb'}"
9
+ puts "Loading enigma gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,106 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Enigma do
4
+
5
+ describe "when generating an API key" do
6
+ it "should be a string" do
7
+ Enigma.generate_key.should be_a(String)
8
+ end
9
+
10
+ it "should be 32 digits long" do
11
+ Enigma.generate_key.length.should == 32
12
+ end
13
+ end
14
+
15
+ describe "when generating an API secret" do
16
+ it "should be a string" do
17
+ Enigma.generate_secret.should be_a(String)
18
+ end
19
+
20
+ it "should be 64 digits long" do
21
+ Enigma.generate_secret.length.should == 32
22
+ end
23
+ end
24
+
25
+ describe "when authenticating" do
26
+ before :each do
27
+ @key = Enigma.generate_key
28
+ # Sigh, has to be global to be seen below...
29
+ @secret = $secret = Enigma.generate_secret
30
+ @params = { :p1 => 1, :p2 => 2 }
31
+ @signed_params = Enigma.encode_params(@secret, @params)
32
+
33
+ end
34
+
35
+ context "with a valid key/secret pair" do
36
+ before :each do
37
+ # Let's just return the secret, straight up.
38
+ Enigma.find_secret do |key|
39
+ $secret
40
+ end
41
+ end
42
+
43
+ it "should return the decoded parameters" do
44
+ Enigma.authenticate(:key => @key, :params => @signed_params).should == @params
45
+ end
46
+ end
47
+
48
+ context "with an invalid key/secret pair" do
49
+ before :each do
50
+ # And now, let's return the wrong one.
51
+ Enigma.find_secret do |key|
52
+ Enigma.generate_secret
53
+ end
54
+ end
55
+
56
+ it "should not be able to decode the params using the invalid secret" do
57
+ Enigma.decode_params(Enigma.generate_secret, @signed_params).should be_nil
58
+ end
59
+
60
+ it "should return nil" do
61
+ Enigma.authenticate(:key => @key, :params => @signed_params).should be_nil
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "when encoding parameters" do
67
+ before :each do
68
+ @secret = Enigma.generate_secret
69
+ @params = { 'param1' => '1', 'param2' => 2 }
70
+ end
71
+
72
+ it "should be able to decode them" do
73
+ Enigma.decode_params(@secret, Enigma.encode_params(@secret, @params)).should == @params
74
+ end
75
+ end
76
+
77
+ end
78
+
79
+ describe Enigma::Client do
80
+ describe "get" do
81
+ before :each do
82
+ @key = Enigma.generate_key
83
+ @secret = Enigma.generate_secret
84
+ @client = Enigma::Client.new(@key, @secret)
85
+ @params = { 'p1' => 'value' }
86
+ @signed_params = Enigma.encode_params(@secret, @params)
87
+ end
88
+
89
+ it "should send a GET request with the key and signed params" do
90
+ RestClient.should_receive(:get).with("http://some.service?params=#{@signed_params}&key=#{@key}")
91
+ @client.get("http://some.service", @params)
92
+ end
93
+ end
94
+ end
95
+
96
+ =begin
97
+ get '/' do
98
+ user = User.find_by_key(params[:key])
99
+ Enigma.authenticate(params[:key], user.secret, params[:params])
100
+ end
101
+
102
+ Enigma.generate_key
103
+ Enigma.generate_secret
104
+
105
+ =end
106
+
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,10 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'enigma'
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enigma
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - T.J. VanSlyke
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-04-03 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ezcrypto
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.7.2
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rubyforge
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.3
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: gemcutter
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.5.0
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: hoe
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 2.5.0
54
+ version:
55
+ description: Key/secret authentication for your web services
56
+ email:
57
+ - teejay.vanslyke@gmail.com
58
+ executables: []
59
+
60
+ extensions: []
61
+
62
+ extra_rdoc_files:
63
+ - History.txt
64
+ - Manifest.txt
65
+ - PostInstall.txt
66
+ files:
67
+ - History.txt
68
+ - Manifest.txt
69
+ - PostInstall.txt
70
+ - README.rdoc
71
+ - Rakefile
72
+ - lib/enigma.rb
73
+ - script/console
74
+ - script/destroy
75
+ - script/generate
76
+ - spec/enigma_spec.rb
77
+ - spec/spec.opts
78
+ - spec/spec_helper.rb
79
+ - tasks/rspec.rake
80
+ has_rdoc: true
81
+ homepage: http://github.com/teejayvanslyke/enigma
82
+ licenses: []
83
+
84
+ post_install_message: PostInstall.txt
85
+ rdoc_options:
86
+ - --main
87
+ - README.rdoc
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ version:
102
+ requirements: []
103
+
104
+ rubyforge_project: enigma
105
+ rubygems_version: 1.3.5
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: Key/secret authentication for your web services
109
+ test_files: []
110
+