salty_dog 0.1.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.
- checksums.yaml +7 -0
- data/lib/salty_dog/salty_dog.rb +143 -0
- data/lib/salty_dog.rb +1 -0
- metadata +77 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b6e3d2c400d8da82752ae6862e1de092d9596e1b
|
4
|
+
data.tar.gz: c22eabb1c6afff27a88fe6927114e2fd0a782dd3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1a523b3345361daf452930cb9cc23de6fb3ee2fff54d015835a47bdb4fbe5f5ce7abfe271e34712f2c58715f2bd0b8fb2710a5c08fe76ad70e9f789e3aa7d343
|
7
|
+
data.tar.gz: 74675135cd008d478a1376232b614ac804946be2246c984c107d056466b9f76dad8ca853ffdec2316d098a514aa2ef240852ecd9be38936a29561ba40056b3ae
|
@@ -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], options[:salt], @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
|
+
|
data/lib/salty_dog.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'salty_dog/salty_dog'
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: salty_dog
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brennon Bortz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-04-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: simplecov
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.7.1
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.7.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: turn
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.6
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.9.6
|
41
|
+
description: A complete, RFC compliant implementation of PBKDF2. As opposed to other
|
42
|
+
PBKDF2 gems, all parameters to the key-derivation function are completely and easily
|
43
|
+
customizable.
|
44
|
+
email: brennon@brennonbortz.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- lib/salty_dog.rb
|
50
|
+
- lib/salty_dog/salty_dog.rb
|
51
|
+
homepage: http://github.com/brennon/salty_dog
|
52
|
+
licenses:
|
53
|
+
- BSD-3
|
54
|
+
metadata: {}
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --main
|
58
|
+
- README.md
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 2.0.3
|
74
|
+
signing_key:
|
75
|
+
specification_version: 4
|
76
|
+
summary: PBKDF2, Ruby-style
|
77
|
+
test_files: []
|