salty_dog 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/salty_dog/salty_dog.rb +143 -0
  3. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30b45203cebf55800a2af8565e63cac6dd99e483
4
- data.tar.gz: e635b9214221bc0015775cdfa44fe70c596698fb
3
+ metadata.gz: 35c2752e30819d70e0038f210d71b46a92d81c85
4
+ data.tar.gz: 7f79e478fb8f2a658f7ba8a7e499fadfc9309b1c
5
5
  SHA512:
6
- metadata.gz: 9e669451237166a5db10484a5296069d3f66e603faa435dddf396d1edf1304b343f7fba4d1e0b12d94ca7e42d0bba7d235c5b80352bae9d95a7a7e726e56e83f
7
- data.tar.gz: 460199701063cd37f868f0979185a129243f059e07659af2862abdf2c3fc2e7c4d61abefd249a62ed291d4738aecc09a090fab53572156c77412e57829b90368
6
+ metadata.gz: f6ddfd7b180e95a1cfb0c4f31316a3c62574662a4977eb09de941d10b8f9d9a7146b13af12701c0bfbf0901242dd9a0bee030b8d0b19e4f7b174aa712225382f
7
+ data.tar.gz: 38a97773ca711de242e850c4fcf7c403a782a600fbeff5c770a4fc8afd679096a6808091e6fc2b4c7165b7ccd68ba24342e230bfb4c0f797ec20909d1ed04514
@@ -0,0 +1,143 @@
1
+ require 'openssl'
2
+
3
+ module SaltyDog
4
+
5
+ ##
6
+ # PBKDF2 encapsulates the identically-named password-based key derivation
7
+ # function outlined in PKCS[http://www.rsa.com/rsalabs/node.asp?id=2127] #5: Password-Based Cryptography Standard. PBKDF1, as set
8
+ # forth in the same document, has been recommended for removal from use, and
9
+ # thus is not implemented in SaltyDog. If you just need to generate keys,
10
+ # skip down to ::digest:
11
+
12
+ class PBKDF2
13
+
14
+ ##
15
+ # According to the recommendation, the hash functions that are supported
16
+ # for HMAC (pseudorandom number generation) are SHA1, SHA224, SHA256,
17
+ # SHA384, AND SHA512. These are provided here.
18
+
19
+ ALLOWED_DIGESTS = [:sha1, :sha224, :sha256, :sha384, :sha512]
20
+
21
+ ##
22
+ # The primary point of entry for SaltyDog::PBKDF2. The available options
23
+ # are:
24
+ #
25
+ # - :digest - One of +:sha1+, +:sha224+, +:sha256+, +:sha384+, or
26
+ # +:sha512+. Defaults to +:sha512+.
27
+ # - :password - A password for use in deriving the key. Required, and must be a string.
28
+ # - :salt - A salt that is concatenated to the password in key derivation.
29
+ # Required, and must ba a string.
30
+ # - :length - The desired length, in bytes, of the derived key. Required.
31
+ # - :iterations - The number of iterations to be used in key derivation.
32
+ # Defaults to 10000.
33
+ #
34
+ # Returns a hex-string representing the derived key.
35
+
36
+ def self.digest(options = {})
37
+ digest = options[:digest] || :sha512
38
+ self.build_digest(digest)
39
+
40
+ check_key_length_requirements(options[:length])
41
+ @length = options[:length]
42
+ @iterations = options[:iterations] || 10000
43
+
44
+ @l = (@length / @digest.length).ceil
45
+ @r = @length - (@l - 1) * @digest.length
46
+
47
+ self.calculate_key(@digest, options[:password].to_s, options[:salt].to_s, @l, @r, @iterations).unpack('H*')[0]
48
+ end
49
+
50
+ ##
51
+ # Build the derived key. Called directly by SaltyDog::PBKDF2.digest.
52
+
53
+ def self.build_digest(digest)
54
+ if !ALLOWED_DIGESTS.include?(digest)
55
+ raise PBKDF2Error, 'Invalid digest'
56
+ end
57
+
58
+ klass = "OpenSSL::Digest::#{digest.to_s.upcase}"
59
+ @digest = Object::const_get(klass).new
60
+ end
61
+
62
+ ##
63
+ # Check desired key length requirements. These are:
64
+ #
65
+ # - Must be present
66
+ # - Must be strictly positive
67
+ # - Must be no larger than (2^32 - 1) * digest length of the chosen hash
68
+ # function
69
+ #
70
+ # Raises a PBKDF2Error if any of these requirements are not met.
71
+
72
+ def self.check_key_length_requirements(length)
73
+ raise PBKDF2Error, 'A key length must be provided' if !length
74
+ raise PBKDF2Error, 'Desired key is too long' if ((2**32 - 1) * @digest.length) < length
75
+ raise PBKDF2Error, 'Desired key length must be positive' if length < 0
76
+ end
77
+
78
+ ##
79
+ # XOR two strings +x+ and +y+.
80
+ #
81
+ # Raises a PBKDF2Error if +a+ and +b+ are not the same length.
82
+ #
83
+ # Returns a string of bytes representing the XORed value.
84
+
85
+ def self.xor(x, y)
86
+ raise PBKDF2Error, 'XOR arguments are not the same length' if x.length - y.length != 0
87
+ output = "".encode('ASCII-8BIT')
88
+
89
+ x.bytes.zip(y.bytes) { |x,y| output << (x^y) }
90
+ output
91
+ end
92
+
93
+ ##
94
+ # Uses a pseudorandom function based on the digest function provided to
95
+ # SaltyDog::PBKDF2.digest to generate input for each iteration round.
96
+
97
+ def self.prf(digest, password, seed)
98
+ raise PBKDF2Error if !password || !seed
99
+ OpenSSL::HMAC.digest(digest, password, seed)
100
+ end
101
+
102
+ ##
103
+ # Within each iteration, SaltyDog::PBKDF2.xor_sum XORs each block of output
104
+ # from SaltyDog::PBKDF2.prf. The result of this chain of XORs is provided
105
+ # to ::calculate_key to be used as a block of the final derived key.
106
+
107
+ def self.xor_sum(digest, password, salt, iterations, block_number)
108
+ packed_index = [block_number].pack("N")
109
+ seed = salt + packed_index
110
+ final = self.prf(digest, password, seed)
111
+ u = final
112
+
113
+ for i in 2..iterations do
114
+ u = self.prf(digest, password, u)
115
+ final = self.xor(final, u)
116
+ end
117
+
118
+ final
119
+ end
120
+
121
+ ##
122
+ # The workhorse of SaltyDog::PBKDF2. ::calculate_key initiates the
123
+ # specified number of iterations of hashing in calculating each block of
124
+ # the derived key. All blocks are then concatenated together in computing
125
+ # the final derived key.
126
+
127
+ def self.calculate_key(digest, password, salt, l, r, iterations)
128
+ t = ""
129
+
130
+ for i in 1..l+1 do
131
+ t << self.xor_sum(digest, password, salt, iterations, i)
132
+ end
133
+
134
+ total_length = digest.length * (l-1) + r
135
+ sliced = t.slice(0..total_length - 1)
136
+ sliced
137
+ end
138
+ end
139
+
140
+ class PBKDF2Error < StandardError
141
+ end
142
+ end
143
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: salty_dog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brennon Bortz
@@ -47,6 +47,7 @@ extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
49
  - lib/salty_dog.rb
50
+ - lib/salty_dog/salty_dog.rb
50
51
  homepage: http://github.com/brennon/salty_dog
51
52
  licenses:
52
53
  - BSD-3