PageRenderTime 52ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/ruby/1.9/digest/hmac.rb

https://bitbucket.org/nicksieger/jruby
Ruby | 281 lines | 203 code | 33 blank | 45 comment | 7 complexity | 341ecb2f960264b080a4aea0ed54c107 MD5 | raw file
Possible License(s): GPL-3.0, JSON
  1. # = digest/hmac.rb
  2. #
  3. # An implementation of HMAC keyed-hashing algorithm
  4. #
  5. # == Overview
  6. #
  7. # CAUTION: Use of this library is discouraged, because this
  8. # implementation was meant to be experimental but somehow got into the
  9. # 1.9 series without being noticed. Please use OpenSSL::HMAC in the
  10. # "openssl" library instead.
  11. #
  12. # This library adds a method named hmac() to Digest classes, which
  13. # creates a Digest class for calculating HMAC digests.
  14. #
  15. # == Examples
  16. #
  17. # require 'digest/hmac'
  18. #
  19. # # one-liner example
  20. # puts Digest::HMAC.hexdigest("data", "hash key", Digest::SHA1)
  21. #
  22. # # rather longer one
  23. # hmac = Digest::HMAC.new("foo", Digest::RMD160)
  24. #
  25. # buf = ""
  26. # while stream.read(16384, buf)
  27. # hmac.update(buf)
  28. # end
  29. #
  30. # puts hmac.bubblebabble
  31. #
  32. # == License
  33. #
  34. # Copyright (c) 2006 Akinori MUSHA <knu@iDaemons.org>
  35. #
  36. # Documentation by Akinori MUSHA
  37. #
  38. # All rights reserved. You can redistribute and/or modify it under
  39. # the same terms as Ruby.
  40. #
  41. # $Id$
  42. #
  43. warn "use of the experimetal library 'digest/hmac' is discouraged; require 'openssl' and use OpenSSL::HMAC instead." if $VERBOSE
  44. require 'digest'
  45. module Digest
  46. class HMAC < Digest::Class
  47. def initialize(key, digester)
  48. @md = digester.new
  49. block_len = @md.block_length
  50. if key.bytesize > block_len
  51. key = @md.digest(key)
  52. end
  53. ipad = Array.new(block_len, 0x36)
  54. opad = Array.new(block_len, 0x5c)
  55. key.bytes.each_with_index { |c, i|
  56. ipad[i] ^= c
  57. opad[i] ^= c
  58. }
  59. @key = key.freeze
  60. @ipad = ipad.pack('C*').freeze
  61. @opad = opad.pack('C*').freeze
  62. @md.update(@ipad)
  63. end
  64. def initialize_copy(other)
  65. @md = other.instance_eval { @md.clone }
  66. end
  67. def update(text)
  68. @md.update(text)
  69. self
  70. end
  71. alias << update
  72. def reset
  73. @md.reset
  74. @md.update(@ipad)
  75. self
  76. end
  77. def finish
  78. d = @md.digest!
  79. @md.update(@opad)
  80. @md.update(d)
  81. @md.digest!
  82. end
  83. private :finish
  84. def digest_length
  85. @md.digest_length
  86. end
  87. def block_length
  88. @md.block_length
  89. end
  90. def inspect
  91. sprintf('#<%s: key=%s, digest=%s>', self.class.name, @key.inspect, @md.inspect.sub(/^\#<(.*)>$/) { $1 });
  92. end
  93. end
  94. end
  95. if $0 == __FILE__
  96. eval DATA.gets(nil), nil, $0, DATA.lineno
  97. end
  98. __END__
  99. require 'test/unit'
  100. module TM_HMAC
  101. def test_s_hexdigest
  102. cases.each { |h|
  103. digesters.each { |d|
  104. assert_equal(h[:hexdigest], Digest::HMAC.hexdigest(h[:data], h[:key], d))
  105. }
  106. }
  107. end
  108. def test_hexdigest
  109. cases.each { |h|
  110. digesters.each { |d|
  111. hmac = Digest::HMAC.new(h[:key], d)
  112. hmac.update(h[:data])
  113. assert_equal(h[:hexdigest], hmac.hexdigest)
  114. }
  115. }
  116. end
  117. def test_reset
  118. cases.each { |h|
  119. digesters.each { |d|
  120. hmac = Digest::HMAC.new(h[:key], d)
  121. hmac.update("test")
  122. hmac.reset
  123. hmac.update(h[:data])
  124. assert_equal(h[:hexdigest], hmac.hexdigest)
  125. }
  126. }
  127. end
  128. end
  129. class TC_HMAC_MD5 < Test::Unit::TestCase
  130. include TM_HMAC
  131. def digesters
  132. [Digest::MD5, Digest::MD5.new]
  133. end
  134. # Taken from RFC 2202: Test Cases for HMAC-MD5 and HMAC-SHA-1
  135. def cases
  136. [
  137. {
  138. :key => "\x0b" * 16,
  139. :data => "Hi There",
  140. :hexdigest => "9294727a3638bb1c13f48ef8158bfc9d",
  141. }, {
  142. :key => "Jefe",
  143. :data => "what do ya want for nothing?",
  144. :hexdigest => "750c783e6ab0b503eaa86e310a5db738",
  145. }, {
  146. :key => "\xaa" * 16,
  147. :data => "\xdd" * 50,
  148. :hexdigest => "56be34521d144c88dbb8c733f0e8b3f6",
  149. }, {
  150. :key => "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
  151. :data => "\xcd" * 50,
  152. :hexdigest => "697eaf0aca3a3aea3a75164746ffaa79",
  153. }, {
  154. :key => "\x0c" * 16,
  155. :data => "Test With Truncation",
  156. :hexdigest => "56461ef2342edc00f9bab995690efd4c",
  157. }, {
  158. :key => "\xaa" * 80,
  159. :data => "Test Using Larger Than Block-Size Key - Hash Key First",
  160. :hexdigest => "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd",
  161. }, {
  162. :key => "\xaa" * 80,
  163. :data => "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
  164. :hexdigest => "6f630fad67cda0ee1fb1f562db3aa53e",
  165. }
  166. ]
  167. end
  168. end
  169. class TC_HMAC_SHA1 < Test::Unit::TestCase
  170. include TM_HMAC
  171. def digesters
  172. [Digest::SHA1, Digest::SHA1.new]
  173. end
  174. # Taken from RFC 2202: Test Cases for HMAC-MD5 and HMAC-SHA-1
  175. def cases
  176. [
  177. {
  178. :key => "\x0b" * 20,
  179. :data => "Hi There",
  180. :hexdigest => "b617318655057264e28bc0b6fb378c8ef146be00",
  181. }, {
  182. :key => "Jefe",
  183. :data => "what do ya want for nothing?",
  184. :hexdigest => "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79",
  185. }, {
  186. :key => "\xaa" * 20,
  187. :data => "\xdd" * 50,
  188. :hexdigest => "125d7342b9ac11cd91a39af48aa17b4f63f175d3",
  189. }, {
  190. :key => "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
  191. :data => "\xcd" * 50,
  192. :hexdigest => "4c9007f4026250c6bc8414f9bf50c86c2d7235da",
  193. }, {
  194. :key => "\x0c" * 20,
  195. :data => "Test With Truncation",
  196. :hexdigest => "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
  197. }, {
  198. :key => "\xaa" * 80,
  199. :data => "Test Using Larger Than Block-Size Key - Hash Key First",
  200. :hexdigest => "aa4ae5e15272d00e95705637ce8a3b55ed402112",
  201. }, {
  202. :key => "\xaa" * 80,
  203. :data => "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
  204. :hexdigest => "e8e99d0f45237d786d6bbaa7965c7808bbff1a91",
  205. }
  206. ]
  207. end
  208. end
  209. class TC_HMAC_RMD160 < Test::Unit::TestCase
  210. include TM_HMAC
  211. def digesters
  212. [Digest::RMD160, Digest::RMD160.new]
  213. end
  214. # Taken from RFC 2286: Test Cases for HMAC-RIPEMD160 and HMAC-RIPEMD128
  215. def cases
  216. [
  217. {
  218. :key => "\x0b" * 20,
  219. :data => "Hi There",
  220. :hexdigest => "24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668",
  221. }, {
  222. :key => "Jefe",
  223. :data => "what do ya want for nothing?",
  224. :hexdigest => "dda6c0213a485a9e24f4742064a7f033b43c4069",
  225. }, {
  226. :key => "\xaa" * 20,
  227. :data => "\xdd" * 50,
  228. :hexdigest => "b0b105360de759960ab4f35298e116e295d8e7c1",
  229. }, {
  230. :key => "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
  231. :data => "\xcd" * 50,
  232. :hexdigest => "d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4",
  233. }, {
  234. :key => "\x0c" * 20,
  235. :data => "Test With Truncation",
  236. :hexdigest => "7619693978f91d90539ae786500ff3d8e0518e39",
  237. }, {
  238. :key => "\xaa" * 80,
  239. :data => "Test Using Larger Than Block-Size Key - Hash Key First",
  240. :hexdigest => "6466ca07ac5eac29e1bd523e5ada7605b791fd8b",
  241. }, {
  242. :key => "\xaa" * 80,
  243. :data => "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
  244. :hexdigest => "69ea60798d71616cce5fd0871e23754cd75d5a0a",
  245. }
  246. ]
  247. end
  248. end