apigee-oauth 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. data/.gitignore +2 -0
  2. data/HISTORY +125 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +70 -0
  5. data/Rakefile +35 -0
  6. data/TODO +32 -0
  7. data/bin/oauth +5 -0
  8. data/examples/yql.rb +44 -0
  9. data/lib/apigee-oauth.rb +12 -0
  10. data/lib/digest/hmac.rb +104 -0
  11. data/lib/oauth/cli.rb +378 -0
  12. data/lib/oauth/client.rb +4 -0
  13. data/lib/oauth/client/action_controller_request.rb +54 -0
  14. data/lib/oauth/client/em_http.rb +94 -0
  15. data/lib/oauth/client/helper.rb +91 -0
  16. data/lib/oauth/client/net_http.rb +127 -0
  17. data/lib/oauth/consumer.rb +383 -0
  18. data/lib/oauth/core_ext.rb +31 -0
  19. data/lib/oauth/errors.rb +3 -0
  20. data/lib/oauth/errors/error.rb +4 -0
  21. data/lib/oauth/errors/problem.rb +14 -0
  22. data/lib/oauth/errors/unauthorized.rb +12 -0
  23. data/lib/oauth/helper.rb +88 -0
  24. data/lib/oauth/oauth.rb +13 -0
  25. data/lib/oauth/oauth_test_helper.rb +25 -0
  26. data/lib/oauth/request_proxy.rb +24 -0
  27. data/lib/oauth/request_proxy/action_controller_request.rb +61 -0
  28. data/lib/oauth/request_proxy/base.rb +166 -0
  29. data/lib/oauth/request_proxy/curb_request.rb +55 -0
  30. data/lib/oauth/request_proxy/em_http_request.rb +67 -0
  31. data/lib/oauth/request_proxy/jabber_request.rb +41 -0
  32. data/lib/oauth/request_proxy/mock_request.rb +44 -0
  33. data/lib/oauth/request_proxy/net_http.rb +72 -0
  34. data/lib/oauth/request_proxy/rack_request.rb +40 -0
  35. data/lib/oauth/request_proxy/typhoeus_request.rb +53 -0
  36. data/lib/oauth/server.rb +66 -0
  37. data/lib/oauth/signature.rb +45 -0
  38. data/lib/oauth/signature/base.rb +110 -0
  39. data/lib/oauth/signature/hmac/base.rb +15 -0
  40. data/lib/oauth/signature/hmac/md5.rb +8 -0
  41. data/lib/oauth/signature/hmac/rmd160.rb +8 -0
  42. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  43. data/lib/oauth/signature/hmac/sha2.rb +8 -0
  44. data/lib/oauth/signature/md5.rb +13 -0
  45. data/lib/oauth/signature/plaintext.rb +23 -0
  46. data/lib/oauth/signature/rsa/sha1.rb +46 -0
  47. data/lib/oauth/signature/sha1.rb +13 -0
  48. data/lib/oauth/token.rb +7 -0
  49. data/lib/oauth/tokens/access_token.rb +68 -0
  50. data/lib/oauth/tokens/consumer_token.rb +33 -0
  51. data/lib/oauth/tokens/request_token.rb +32 -0
  52. data/lib/oauth/tokens/server_token.rb +9 -0
  53. data/lib/oauth/tokens/token.rb +17 -0
  54. data/tasks/deployment.rake +34 -0
  55. data/tasks/environment.rake +7 -0
  56. data/tasks/website.rake +17 -0
  57. data/test/cases/oauth_case.rb +19 -0
  58. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  59. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  60. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  61. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  62. data/test/integration/consumer_test.rb +304 -0
  63. data/test/keys/rsa.cert +11 -0
  64. data/test/keys/rsa.pem +16 -0
  65. data/test/test_access_token.rb +26 -0
  66. data/test/test_action_controller_request_proxy.rb +132 -0
  67. data/test/test_consumer.rb +159 -0
  68. data/test/test_curb_request_proxy.rb +76 -0
  69. data/test/test_em_http_client.rb +79 -0
  70. data/test/test_em_http_request_proxy.rb +114 -0
  71. data/test/test_helper.rb +20 -0
  72. data/test/test_hmac_sha1.rb +20 -0
  73. data/test/test_net_http_client.rb +282 -0
  74. data/test/test_net_http_request_proxy.rb +72 -0
  75. data/test/test_oauth_helper.rb +49 -0
  76. data/test/test_rack_request_proxy.rb +40 -0
  77. data/test/test_request_token.rb +51 -0
  78. data/test/test_rsa_sha1.rb +59 -0
  79. data/test/test_server.rb +40 -0
  80. data/test/test_signature.rb +22 -0
  81. data/test/test_signature_base.rb +32 -0
  82. data/test/test_signature_plain_text.rb +31 -0
  83. data/test/test_token.rb +14 -0
  84. data/test/test_typhoeus_request_proxy.rb +80 -0
  85. metadata +287 -0
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ _site
data/HISTORY ADDED
@@ -0,0 +1,125 @@
1
+ == 0.4.0 2010-04-22
2
+
3
+ * Added computation of oauth_body_hash as per OAuth Request Body Hash 1.0
4
+ Draft 4 (Michael Reinsch)
5
+ * Added the optional `oauth_session_handle` parameter for the Yahoo implementation (Will Bailey)
6
+ * Better marshalling implementation (Yoan Blanc)
7
+ * Added optional block to OAuth::Consumer.get_*_token (Neill Pearman)
8
+ * Exclude `oauth_callback` with :exclude_callback (Neill Pearman)
9
+ * Strip extraneous spaces and line breaks from access_token responses
10
+ (observed in the wild with Yahoo!'s OAuth+OpenID hybrid) (Eric Hartmann)
11
+ * Stop double-escaping PLAINTEXT signatures (Jimmy Zimmerman)
12
+ * OAuth::Client::Helper won't override the specified `oauth_version`
13
+ (Philip Kromer)
14
+ * Support for Ruby 1.9 (Aaron Quint, Corey Donahoe, et al)
15
+ * Fixed an encoding / multibyte issue (成田 一生)
16
+ * Replaced hoe with Jeweler (Aaron Quint)
17
+ * Support for Typhoeus (Bill Kocik)
18
+ * Support for em-http (EventMachine) (Darcy Laycock)
19
+ * Support for curb (André Luis Leal Cardoso Junior)
20
+ * New website (Aaron Quint)
21
+
22
+ == 0.3.6 2009-09-14
23
+
24
+ * Added -B CLI option to use the :body authentication scheme (Seth)
25
+ * Respect `--method` in `authorize` CLI command (Seth)
26
+ * Support POST and PUT with raw bodies (Yu-Shan Fung et al)
27
+ * Test clean-up (Xavier Shay, Hannes Tydén)
28
+ * Added :ca_file consumer option to allow consumer specific certificate
29
+ override. (Pelle)
30
+
31
+ == 0.3.5 2009-06-03
32
+
33
+ * `query` CLI command to access protected resources (Seth)
34
+ * Added -H, -Q CLI options for specifying the authentication scheme (Seth)
35
+ * Added -O CLI option for specifying a file containing options (Seth)
36
+ * Support streamable body contents for large request bodies (Seth Cousins)
37
+ * Support for OAuth 1.0a (Seth)
38
+ * Added proxy support to OAuth::Consumer (Marshall Huss)
39
+ * Added --scope CLI option for Google's 'scope' parameter (Seth)
40
+
41
+ == 0.3.4 2009-05-06
42
+
43
+ * OAuth::Client::Helper uses OAuth::VERSION (chadisfaction)
44
+ * Fix OAuth::RequestProxy::ActionControllerRequest's handling of params
45
+ (Tristan Groléat)
46
+
47
+ == 0.3.3 2009-05-04
48
+
49
+ * Corrected OAuth XMPP namespace (Seth)
50
+ * Improved error handling for invalid Authorization headers (Matt Sanford)
51
+ * Fixed signatures for non-ASCII under $KCODE other than 'u' (Matt Sanford)
52
+ * Fixed edge cases in ActionControllerRequestProxy where params were being
53
+ incorrectly signed (Marcos Wright Kuhns)
54
+ * Support for arguments in OAuth::Consumer#get_access_token (Matt Sanford)
55
+ * Add gem version to user-agent header (Matt Sanford)
56
+ * Handle input from aggressive form encoding libraries (Matt Wood)
57
+
58
+ == 0.3.2 2009-03-23
59
+
60
+ * 2xx statuses should be treated as success (Anders Conbere)
61
+ * Support applications using the MethodOverride Rack middleware (László Bácsi)
62
+ * `authorize` command for `oauth` CLI (Seth)
63
+ * Initial support for Problem Reporting extension (Seth)
64
+ * Verify SSL certificates if CA certificates are available (Seth)
65
+ * Fixed ActionController parameter escaping behavior (Thiago Arrais, László
66
+ Bácsi, Brett Gibson, et al)
67
+ * Fixed signature calculation when both options and a block were provided to
68
+ OAuth::Signature::Base#initialize (Seth)
69
+ * Added help to the 'oauth' CLI (Seth)
70
+ * Fixed a problem when attempting to normalize MockRequest URIs (Seth)
71
+
72
+ == 0.3.1 2009-1-26
73
+
74
+ * Fixed a problem with relative and absolute token request paths. (Michael
75
+ Wood)
76
+
77
+ == 0.3.0 2009-1-25
78
+
79
+ * Support ActionController::Request from Edge Rails (László Bácsi)
80
+ * Correctly handle multi-valued parameters (Seth)
81
+ * Added #normalized_parameters to OAuth::RequestProxy::Base (Pelle)
82
+ * OAuth::Signature.sign and friends now yield the RequestProxy instead of the
83
+ token when the passed block's arity is 1. (Seth)
84
+ * Token requests are made to the configured URL rather than generating a
85
+ potentially incorrect one. (Kellan Elliott-McCrea)
86
+ * Command-line app for generating signatures. (Seth)
87
+ * Improved test-cases and compatibility for encoding issues. (Pelle)
88
+
89
+ == 0.2.7 2008-9-10 The lets fix the last release release
90
+
91
+ * Fixed plain text signatures (Andrew Arrow)
92
+ * Fixed RSA requests using OAuthTokens. (Philip Lipu Tsai)
93
+
94
+ == 0.2.6 2008-9-9 The lets RSA release
95
+
96
+ * Improved support for Ruby 1.8.7 (Bill Kocik)
97
+ * Fixed RSA verification to support RSA providers
98
+ now using Ruby and RSA
99
+ * Improved RSA testing
100
+ * Omit token when signing with RSA
101
+ * Added support for 'private_key_file' option for RSA signatures (Chris Mear)
102
+ * Fixed several edge cases where params were being incorrectly signed (Scott
103
+ Hill)
104
+ * Fixed RSA signing (choonkeat)
105
+
106
+ == 0.2.2 2008-2-22 Lets actually support SSL release
107
+
108
+ * Use HTTPS when required.
109
+
110
+ == 0.2 2008-1-19 All together now release
111
+
112
+ This is a big release, where we have merged the efforts of various parties into one common library.
113
+ This means there are definitely some API changes you should be aware of. They should be minimal
114
+ but please have a look at the unit tests.
115
+
116
+ == 0.1.2 2007-12-1
117
+
118
+ * Fixed checks for missing OAuth params to improve performance
119
+ * Includes Pat's fix for getting the realm out.
120
+
121
+ == 0.1.1 2007-11-26
122
+
123
+ * First release as a GEM
124
+ * Moved all non-Rails functionality from the Rails plugin:
125
+ http://code.google.com/p/oauth-plugin/
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Blaine Cook, Larry Halff, Pelle Braendgaard
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,70 @@
1
+ = Ruby OAuth
2
+
3
+ == What
4
+
5
+ This is a RubyGem for implementing both OAuth clients and servers in Ruby applications.
6
+
7
+ See the OAuth specs http://oauth.net/core/1.0/
8
+
9
+ == Installing
10
+
11
+ sudo gem install oauth
12
+
13
+ The source code is now hosted on the OAuth GitHub Project http://github.com/oauth/oauth-ruby
14
+
15
+ == The basics
16
+
17
+ This is a ruby library which is intended to be used in creating Ruby Consumer and Service Provider applications. It is NOT a Rails plugin, but could easily be used for the foundation for such a Rails plugin.
18
+
19
+ As a matter of fact it has been pulled out from an OAuth Rails Plugin http://code.google.com/p/oauth-plugin/ which now requires this GEM.
20
+
21
+ == Demonstration of usage
22
+
23
+ Create a new consumer instance by passing it a configuration hash:
24
+
25
+ @consumer = OAuth::Consumer.new("key","secret", :site => "https://agree2")
26
+
27
+ Start the process by requesting a token
28
+
29
+ @request_token = @consumer.get_request_token
30
+ session[:request_token] = @request_token
31
+ redirect_to @request_token.authorize_url
32
+
33
+ When user returns create an access_token
34
+
35
+ @access_token = @request_token.get_access_token
36
+ @photos = @access_token.get('/photos.xml')
37
+
38
+ Now that you have an access token, you can use Typhoeus to interact with the OAuth provider if you choose.
39
+
40
+ oauth_params = {:consumer => oauth_consumer, :token => access_token}
41
+ hydra = Typhoeus::Hydra.new
42
+ req = Typhoeus::Request.new(uri, options)
43
+ oauth_helper = OAuth::Client::Helper.new(req, oauth_params.merge(:request_uri => uri))
44
+ req.headers.merge!({"Authorization" => oauth_helper.header}) # Signs the request
45
+ hydra.queue(req)
46
+ hydra.run
47
+ @response = req.response
48
+
49
+
50
+ == More Information
51
+
52
+ * RDoc: http://rdoc.info/projects/oauth/oauth-ruby/
53
+ * Mailing List/Google Group: http://groups.google.com/group/oauth-ruby
54
+
55
+ == How to submit patches
56
+
57
+ The source code is now hosted on the OAuth GitHub Project http://github.com/oauth/oauth-ruby
58
+
59
+ To submit a patch, please fork the oauth project and create a patch with tests. Once you're happy with it send a pull request and post a message to the google group.
60
+
61
+ == License
62
+
63
+ This code is free to use under the terms of the MIT license.
64
+
65
+ == Contact
66
+
67
+ OAuth Ruby has been created and maintained by a large number of talented individuals.
68
+ The current maintainer is Aaron Quint (quirkey).
69
+
70
+ Comments are welcome. Send an email to via the OAuth Ruby mailing list http://groups.google.com/group/oauth-ruby
@@ -0,0 +1,35 @@
1
+ %w[rubygems rake rake/clean rake/testtask fileutils].each { |f| require f }
2
+ $LOAD_PATH << File.dirname(__FILE__) + '/lib'
3
+ require 'apigee-oauth'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |s|
8
+ s.name = %q{apigee-oauth}
9
+ s.version = OAuth::VERSION
10
+ s.authors = ["Pelle Braendgaard", "Blaine Cook", "Larry Halff", "Jesse Clark", "Jon Crosby", "Seth Fitzsimmons", "Matt Sanford", "Aaron Quint"]
11
+ s.email = "oauth-ruby@googlegroups.com"
12
+ s.description = "OAuth Core Ruby implementation"
13
+ s.summary = s.description
14
+ s.rubyforge_project = %q{apigee-oauth}
15
+ s.add_development_dependency(%q<actionpack>, [">= 2.2.0", "<2.3.0"])
16
+ s.add_development_dependency(%q<rack>, [">= 1.0.0"])
17
+ s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
18
+ s.add_development_dependency(%q<typhoeus>, [">= 0.1.13"])
19
+ s.add_development_dependency(%q<em-http-request>)
20
+ s.add_development_dependency(%q<curb>, [">= 0.6.6.0"])
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
25
+ end
26
+
27
+ Rake::TestTask.new do |t|
28
+ t.libs << "test"
29
+ t.test_files = FileList['test/*test*.rb']
30
+ t.verbose = true
31
+ end
32
+
33
+ Dir['tasks/**/*.rake'].each { |t| load t }
34
+
35
+ task :default => :test
data/TODO ADDED
@@ -0,0 +1,32 @@
1
+ Common use-cases should be streamlined:
2
+
3
+ * I have a URL that I want to sign (given consumer key/secret, optional
4
+ token/secret, optional nonce/timestamp).
5
+ * I have a URL that I want to sign AND I want to see what the components
6
+ (e.g. signature base string, etc.) are while it's being signed (i.e. verbose
7
+ signing).
8
+ * I have a URL that I want to sign and I only want the signature.
9
+ * I have a URL that I want to sign and I want something suitable to put in
10
+ {the header, the querystring, XMPP}.
11
+ * I want to make a query to an OAuth-enabled web service (with sensible
12
+ errors, if available).
13
+ * I want to host an OAuth-enabled web service.
14
+ * I want to test my OAuth-enabled web service (i.e. test helpers)
15
+
16
+ Example applications for:
17
+ * Ning
18
+ * Fire Eagle
19
+ * Google (blogger, contacts)
20
+ * Twitter
21
+ * YOS / YQL
22
+ * Netflix
23
+
24
+ In addition to providing best practices of use, these can also be part of
25
+ the pre-release checks to make sure that there have been no regressions.
26
+
27
+ Random TODOs:
28
+ * finish CLI
29
+ * sensible Exception hierarchy
30
+ * Tokens as Modules
31
+ * don't tie to Net::HTTP
32
+ * Take a look at Curb HTTP Verbs
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "oauth/cli"
4
+
5
+ OAuth::CLI.execute(STDOUT, STDIN, STDERR, ARGV)
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby -rubygems
2
+
3
+ # Sample queries:
4
+ # ./yql.rb --consumer-key <key> --consumer-secret <secret> "show tables"
5
+ # ./yql.rb --consumer-key <key> --consumer-secret <secret> "select * from flickr.photos.search where text='Cat' limit 10"
6
+
7
+ require 'oauth'
8
+ require 'optparse'
9
+ require 'json'
10
+ require 'pp'
11
+
12
+ options = {}
13
+
14
+ option_parser = OptionParser.new do |opts|
15
+ opts.banner = "Usage: #{$0} [options] <query>"
16
+
17
+ opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
18
+ options[:consumer_key] = v
19
+ end
20
+
21
+ opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
22
+ options[:consumer_secret] = v
23
+ end
24
+ end
25
+
26
+ option_parser.parse!
27
+ query = ARGV.pop
28
+ query = STDIN.read if query == "-"
29
+
30
+ if options[:consumer_key].nil? || options[:consumer_secret].nil? || query.nil?
31
+ puts option_parser.help
32
+ exit 1
33
+ end
34
+
35
+ consumer = OAuth::Consumer.new \
36
+ options[:consumer_key],
37
+ options[:consumer_secret],
38
+ :site => "http://query.yahooapis.com"
39
+
40
+ access_token = OAuth::AccessToken.new(consumer)
41
+
42
+ response = access_token.request(:get, "/v1/yql?q=#{OAuth::Helper.escape(query)}&format=json")
43
+ rsp = JSON.parse(response.body)
44
+ pp rsp
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH << File.dirname(__FILE__) unless $LOAD_PATH.include?(File.dirname(__FILE__))
2
+
3
+ module OAuth
4
+ VERSION = "0.4.0"
5
+ end
6
+
7
+ require 'oauth/oauth'
8
+ require 'oauth/core_ext'
9
+
10
+ require 'oauth/client/helper'
11
+ require 'oauth/signature/hmac/sha1'
12
+ require 'oauth/request_proxy/mock_request'
@@ -0,0 +1,104 @@
1
+ # = digest/hmac.rb
2
+ #
3
+ # An implementation of HMAC keyed-hashing algorithm
4
+ #
5
+ # == Overview
6
+ #
7
+ # This library adds a method named hmac() to Digest classes, which
8
+ # creates a Digest class for calculating HMAC digests.
9
+ #
10
+ # == Examples
11
+ #
12
+ # require 'digest/hmac'
13
+ #
14
+ # # one-liner example
15
+ # puts Digest::HMAC.hexdigest("data", "hash key", Digest::SHA1)
16
+ #
17
+ # # rather longer one
18
+ # hmac = Digest::HMAC.new("foo", Digest::RMD160)
19
+ #
20
+ # buf = ""
21
+ # while stream.read(16384, buf)
22
+ # hmac.update(buf)
23
+ # end
24
+ #
25
+ # puts hmac.bubblebabble
26
+ #
27
+ # == License
28
+ #
29
+ # Copyright (c) 2006 Akinori MUSHA <knu@iDaemons.org>
30
+ #
31
+ # Documentation by Akinori MUSHA
32
+ #
33
+ # All rights reserved. You can redistribute and/or modify it under
34
+ # the same terms as Ruby.
35
+ #
36
+ # $Id: hmac.rb 14881 2008-01-04 07:26:14Z akr $
37
+ #
38
+
39
+ require 'digest'
40
+
41
+ unless defined?(Digest::HMAC)
42
+ module Digest
43
+ class HMAC < Digest::Class
44
+ def initialize(key, digester)
45
+ @md = digester.new
46
+
47
+ block_len = @md.block_length
48
+
49
+ if key.bytesize > block_len
50
+ key = @md.digest(key)
51
+ end
52
+
53
+ ipad = Array.new(block_len).fill(0x36)
54
+ opad = Array.new(block_len).fill(0x5c)
55
+
56
+ key.bytes.each_with_index { |c, i|
57
+ ipad[i] ^= c
58
+ opad[i] ^= c
59
+ }
60
+
61
+ @key = key.freeze
62
+ @ipad = ipad.inject('') { |s, c| s << c.chr }.freeze
63
+ @opad = opad.inject('') { |s, c| s << c.chr }.freeze
64
+ @md.update(@ipad)
65
+ end
66
+
67
+ def initialize_copy(other)
68
+ @md = other.instance_eval { @md.clone }
69
+ end
70
+
71
+ def update(text)
72
+ @md.update(text)
73
+ self
74
+ end
75
+ alias << update
76
+
77
+ def reset
78
+ @md.reset
79
+ @md.update(@ipad)
80
+ self
81
+ end
82
+
83
+ def finish
84
+ d = @md.digest!
85
+ @md.update(@opad)
86
+ @md.update(d)
87
+ @md.digest!
88
+ end
89
+ private :finish
90
+
91
+ def digest_length
92
+ @md.digest_length
93
+ end
94
+
95
+ def block_length
96
+ @md.block_length
97
+ end
98
+
99
+ def inspect
100
+ sprintf('#<%s: key=%s, digest=%s>', self.class.name, @key.inspect, @md.inspect.sub(/^\#<(.*)>$/) { $1 });
101
+ end
102
+ end
103
+ end
104
+ end