dionysus 0.3.0 → 0.3.1

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.
data/Rakefile CHANGED
@@ -44,3 +44,5 @@ Rake::RDocTask.new do |rdoc|
44
44
  rdoc.rdoc_files.include('README*', 'LICENSE', 'VERSION')
45
45
  rdoc.rdoc_files.include('lib/**/*.rb')
46
46
  end
47
+
48
+ task :clobber => [:clobber_rcov, :clobber_rdoc]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.1
data/dionysus.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dionysus}
8
- s.version = "0.3.0"
8
+ s.version = "0.3.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Travis D. Warlick, Jr."]
12
- s.date = %q{2010-04-02}
12
+ s.date = %q{2010-04-04}
13
13
  s.email = %q{warlickt@operissystems.com}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
@@ -65,21 +65,15 @@ module Digest
65
65
  ##
66
66
  # The lengths of the registered digests in the given encoding.
67
67
  def self.digest_lengths( encoding = :binary )
68
- if encoding.is_a?(Symbol)
69
- bits_per_char = case encoding
70
- when :binary then 8
71
- when :base64 then 6
72
- when :hex, :hexidecimal then 4
73
- when :bit then 1
74
- else raise ArgumentError, "Invalid encoding"
75
- end
68
+ if encoding == :bit or encoding == 1
69
+ _digest_lengths(1)
70
+ elsif encoding.is_a?(Symbol) and String::ENCODING_BITS_PER_CHAR[encoding]
71
+ _digest_lengths(String::ENCODING_BITS_PER_CHAR[encoding])
76
72
  elsif encoding.is_a?(Integer) and encoding > 0
77
- bits_per_char = encoding
73
+ _digest_lengths(encoding)
78
74
  else
79
75
  raise ArgumentError, "Invalid encoding"
80
76
  end
81
-
82
- Hash[ self.digests.collect { |dig, info| [dig, info[:bit_length] / bits_per_char] } ]
83
77
  end
84
78
 
85
79
  ##
@@ -89,12 +83,48 @@ module Digest
89
83
  #
90
84
  # Digest.digest(:sha512, 'foobar') #=> binary digest
91
85
  # Digest.digest(Digest::SHA512, 'foobar') #=> binary digest
92
- def self.digest( sym_or_klass, str )
93
- if sym_or_klass.is_a?(Class)
94
- sym_or_klass
95
- else
96
- Digest.const_get(sym_or_klass.to_s.upcase)
97
- end.digest(str)
86
+ def self.digest( sym, str )
87
+ Digest.const_get(sym.to_s.upcase).digest(str)
88
+ end
89
+
90
+ ##
91
+ # Detect the digest of the string. Returns nil if the digest cannot be
92
+ # determined.
93
+ #
94
+ # Example:
95
+ # Digest.detect_digest("wxeCFXPVXePFcpwuFDjonyn1G/w=", :base64) #=> :sha1
96
+ # Digest.detect_digest("foobar", :hex) #=> nil
97
+ def self.detect_digest( string, encoding = :binary )
98
+ string = string.strip unless encoding == :binary
99
+ dig = self.digest_lengths(encoding).invert[string.length]
100
+ dig = :sha256 if dig == :sha2
101
+ dig
102
+ end
103
+
104
+ ##
105
+ # Detect the digest of the string. Returns nil if the digest cannot be
106
+ # determined.
107
+ #
108
+ # Example:
109
+ # Digest.detect_digest!("wxeCFXPVXePFcpwuFDjonyn1G/w=", :base64) #=> :sha1
110
+ # Digest.detect_digest!("foobar", :hex) #=> RuntimeError
111
+ def self.detect_digest!( string, encoding = :binary )
112
+ self.detect_digest(string, encoding) or raise("Unknown digest")
113
+ end
114
+
115
+ private
116
+
117
+ def self._digest_lengths( bits_per_char ) # :nodoc:
118
+ padding_factor = (bits_per_char.lcm(8) / bits_per_char)
119
+
120
+ returning result={} do
121
+ self.digests.each do |dig, info|
122
+ result[dig] = len = info[:bit_length] / bits_per_char
123
+ if (t_ = len % padding_factor) != 0
124
+ result[dig] = len + (padding_factor - t_)
125
+ end
126
+ end
127
+ end
98
128
  end
99
129
  end
100
130
 
@@ -77,19 +77,11 @@ class PasswordSalt
77
77
  # Default: 8
78
78
  def initialize( *args )
79
79
  options = args.extract_options!
80
- if args[0].nil? or args[0] == :new or args[0].is_a?(String)
81
- self.string = args[0] || :new
82
- end
83
80
 
84
- if args[0].is_a?(Symbol) and args[0] != :new
85
- self.placement = args[0]
86
- elsif args[1].is_a?(Symbol)
87
- self.placement = args[1]
88
- else
89
- self.placement = DEFAULT_PLACEMENT
90
- end
81
+ self.string = args.detect { |val| val.is_a?(String) or val == :new }
82
+ self.placement = args.detect { |val| PLACEMENTS.include?(val) } || DEFAULT_PLACEMENT
91
83
 
92
- if self.string == :new
84
+ if self.string == :new or self.string.nil?
93
85
  self.string = self.class.generate(options[:length] || DEFAULT_LENGTH)
94
86
  end
95
87
  end
@@ -53,22 +53,33 @@ class String
53
53
  def method_missing( method, *args )
54
54
  super if block_given?
55
55
 
56
- begin
57
- return self.digest(method, *args)
58
- rescue NameError
56
+ if Digest.available_digests.include?(method)
57
+ self.digest(method, *args)
58
+ else
59
+ super
59
60
  end
60
- super
61
61
  end
62
62
 
63
63
  ##
64
- # Detect the digest of the string
64
+ # Detect the digest of the string. Returns nil if the digest cannot be
65
+ # determined.
66
+ #
67
+ # Example:
68
+ # "wxeCFXPVXePFcpwuFDjonyn1G/w=".detect_digest(:base64) #=> :sha1
69
+ # "foobar".detect_digest(:hex) #=> nil
65
70
  def detect_digest( encoding )
66
- self.class.available_digests.each do |dig|
67
- if ''.digest(dig, :encoding => encoding).length == self.length
68
- return dig
69
- end
70
- end
71
- raise "Unknown digest."
71
+ Digest.detect_digest(self, encoding)
72
+ end
73
+
74
+ ##
75
+ # Detect the digest of the string. Raises "Unknown digest" if the digest
76
+ # cannot be determined.
77
+ #
78
+ # Example:
79
+ # "wxeCFXPVXePFcpwuFDjonyn1G/w=".detect_digest!(:base64) #=> :sha1
80
+ # "foobar".detect_digest!(:hex) #=> RuntimeError
81
+ def detect_digest!( encoding )
82
+ Digest.detect_digest!(self, encoding)
72
83
  end
73
84
 
74
85
  private
@@ -8,6 +8,7 @@ require 'active_support/base64'
8
8
  class String
9
9
  HEX_REGEXP = /^[a-f0-9]+$/
10
10
  BASE64_REGEXP = /^[A-Za-z0-9\+\/\=]+$/
11
+ ENCODING_BITS_PER_CHAR = {:binary => 8, :base64 => 6, :hex => 4, :hexidecimal => 4}
11
12
 
12
13
  ##
13
14
  # Encode the Base64 (without newlines)
data/spec/digest_spec.rb CHANGED
@@ -3,6 +3,8 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
  require 'dionysus/digest'
4
4
 
5
5
  describe Digest do
6
+ DIGESTS = { :md5 => 128, :sha1 => 160, :sha2 => 256,
7
+ :sha256 => 256, :sha384 => 384, :sha512 => 512 }
6
8
  it 'should have the default available digests' do
7
9
  Digest.available_digests.length.should == Digest::DEFAULT_DIGESTS.length
8
10
  Digest::DEFAULT_DIGESTS.each do |dig|
@@ -87,8 +89,7 @@ describe Digest do
87
89
  end
88
90
 
89
91
  describe 'digest lengths' do
90
- { :md5 => 128, :sha1 => 160, :sha2 => 256,
91
- :sha256 => 256, :sha384 => 384, :sha512 => 512 }.each do |dig, bits|
92
+ DIGESTS.each do |dig, bits|
92
93
  it "should have binary length for #{dig}" do
93
94
  Digest.digest_lengths[dig].should == bits / 8
94
95
  Digest.digest_lengths(:binary)[dig].should == bits / 8
@@ -102,8 +103,10 @@ describe Digest do
102
103
  end
103
104
 
104
105
  it "should have base64 length for #{dig}" do
105
- Digest.digest_lengths(:base64)[dig].should == bits / 6
106
- Digest.digest_lengths(6)[dig].should == bits / 6
106
+ len = bits / 6
107
+ expected = (len % 4 == 0 ? len : len + (4 - len % 4))
108
+ Digest.digest_lengths(:base64)[dig].should == expected
109
+ Digest.digest_lengths(6)[dig].should == expected
107
110
  end
108
111
 
109
112
  it "should have bit length for #{dig}" do
@@ -112,14 +115,69 @@ describe Digest do
112
115
  end
113
116
 
114
117
  it "should have arbitrary length for #{dig}" do
115
- Digest.digest_lengths(7)[dig].should == bits / 7
118
+ len = bits / 7
119
+ Digest.digest_lengths(7)[dig].should == len + (8 - len % 8)
116
120
  end
117
121
  end
118
122
 
119
123
  it 'should reject bit length requests for < 0' do
120
- lambda { Digest.digest_lengths(0).should raise_error(ArgumentError, 'Invalid encoding') }
121
- lambda { Digest.digest_lengths(-1).should raise_error(ArgumentError, 'Invalid encoding') }
122
- lambda { Digest.digest_lengths(-100).should raise_error(ArgumentError, 'Invalid encoding') }
124
+ lambda { Digest.digest_lengths(0) }.should raise_error(ArgumentError, 'Invalid encoding')
125
+ lambda { Digest.digest_lengths(-1) }.should raise_error(ArgumentError, 'Invalid encoding')
126
+ lambda { Digest.digest_lengths(-100) }.should raise_error(ArgumentError, 'Invalid encoding')
127
+ end
128
+
129
+ it 'should reject bit length requests for unknown encodings' do
130
+ lambda { Digest.digest_lengths(:my_digest) }.should raise_error(ArgumentError, 'Invalid encoding')
131
+ end
132
+ end
133
+
134
+ describe "digest helper" do
135
+ DIGESTS.each do |dig, bits|
136
+ it "should run the digest for #{dig}" do
137
+ Digest.digest(dig, 'foobar').length.should == bits / 8
138
+ end
139
+
140
+ it "should still have working original digest methods" do
141
+ "Digest::#{dig.to_s.upcase}".constantize.digest('foobar').length.should == bits / 8
142
+ end
143
+ end
144
+
145
+ it "should fail invalid digest" do
146
+ lambda { Digest.digest(:my_digest, 'foobar') }.should raise_error(LoadError)
147
+ end
148
+ end
149
+
150
+ describe "detection" do
151
+ DIGESTS.each do |dig, bits|
152
+ it "should detect #{dig} in binary" do
153
+ str = Digest.digest(dig, 'foobar')
154
+ Digest.detect_digest(str).should == (dig == :sha2 ? :sha256 : dig)
155
+ Digest.detect_digest(str, :binary).should == (dig == :sha2 ? :sha256 : dig)
156
+ Digest.detect_digest!(str).should == (dig == :sha2 ? :sha256 : dig)
157
+ Digest.detect_digest!(str, :binary).should == (dig == :sha2 ? :sha256 : dig)
158
+ end
159
+
160
+ it "should detect #{dig} in base64" do
161
+ str = Digest.digest(dig, 'foobar').encode64s
162
+ Digest.detect_digest(str, :base64).should == (dig == :sha2 ? :sha256 : dig)
163
+ Digest.detect_digest!(str, :base64).should == (dig == :sha2 ? :sha256 : dig)
164
+ end
165
+
166
+ it "should detect #{dig} in hexidecimal" do
167
+ str = Digest.digest(dig, 'foobar').encode_hexidecimal
168
+ Digest.detect_digest(str, :hex).should == (dig == :sha2 ? :sha256 : dig)
169
+ Digest.detect_digest(str, :hexidecimal).should == (dig == :sha2 ? :sha256 : dig)
170
+ Digest.detect_digest!(str, :hex).should == (dig == :sha2 ? :sha256 : dig)
171
+ Digest.detect_digest!(str, :hexidecimal).should == (dig == :sha2 ? :sha256 : dig)
172
+ end
173
+ end
174
+
175
+ it "should return nil on unknown digest" do
176
+ Digest.detect_digest('blah').should be_nil
177
+ end
178
+
179
+ it "should fail on unknown digest with !" do
180
+ lambda { Digest.detect_digest!('blah') }.should raise_error(RuntimeError, "Unknown digest")
123
181
  end
124
182
  end
125
183
  end
@@ -93,6 +93,10 @@ describe PasswordSalt do
93
93
  salt.should_not match(/\A[A-Za-z0-9\+\/]{100}\Z/)
94
94
  end
95
95
  end
96
+
97
+ it "should raise an error with an invalid format" do
98
+ lambda { PasswordSalt.generate(10, :foobar) }.should raise_error(ArgumentError, "Invalid format: foobar")
99
+ end
96
100
  end
97
101
 
98
102
  describe "after placement" do
@@ -110,6 +114,12 @@ describe PasswordSalt do
110
114
  salt = PasswordSalt.new(@salt, :after)
111
115
  salt.salt_password(@password).should == @password+@salt
112
116
  end
117
+
118
+ it "should raise an error with a bad placement" do
119
+ salt = PasswordSalt.new(@salt)
120
+ salt.instance_variable_set('@placement', :foobar)
121
+ lambda { salt.salt_password(@password) }.should raise_error(RuntimeError, "Invalid salt placement: foobar")
122
+ end
113
123
  end
114
124
 
115
125
  describe "before placement" do
@@ -179,4 +179,26 @@ describe String do
179
179
  "abcde\240z405".digest(:md5, :encoding => :binary).should == digest
180
180
  "abcde\240z405".md5(:encoding => :binary).should == digest
181
181
  end
182
+
183
+ it "should fallback to super method missing with unavailable digest" do
184
+ lambda { "abcde\240z405".my_digest }.should raise_error(NoMethodError)
185
+ end
186
+
187
+ it "should raise an error with invalid encoding" do
188
+ lambda { "abcde\240z405".md5(:encoding => :foobar) }.should raise_error(ArgumentError, 'Invalid encoding: foobar')
189
+ end
190
+
191
+ describe "digest detection" do
192
+ it "should defer to Digest" do
193
+ str = "abcde\240z405"
194
+ Digest.should_receive(:detect_digest).with(str, :binary)
195
+ str.detect_digest(:binary)
196
+ end
197
+
198
+ it "should defer to Digest" do
199
+ str = "abcde\240z405"
200
+ Digest.should_receive(:detect_digest!).with(str, :binary)
201
+ str.detect_digest!(:binary)
202
+ end
203
+ end
182
204
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 3
8
- - 0
9
- version: 0.3.0
8
+ - 1
9
+ version: 0.3.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Travis D. Warlick, Jr.
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-02 00:00:00 -05:00
17
+ date: 2010-04-04 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency