phc_string_format 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.reek.yml +25 -0
- data/.rubocop.yml +32 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +44 -1
- data/README.md +15 -2
- data/lib/phc_string_format.rb +8 -56
- data/lib/phc_string_format/b64.rb +21 -0
- data/lib/phc_string_format/formatter.rb +14 -0
- data/lib/phc_string_format/phc_string.rb +83 -0
- data/lib/phc_string_format/version.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f2c0d23fc35b585de7e270b87439a5ae61c53213f10442f8b5e576484e985d2d
|
4
|
+
data.tar.gz: 5ccf72ce6afe6ac8e16a8fb6904341007e7698daf2ddd85b25296d5179c7cca2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59d704eeda40482c8b55c1ee0e398c3da3b09c70fcff60e05106411c8bf2e43246c57d9b6bbaebf2af5f1ae855105ce915847bee79a09bb67f2b3436d5b21bb6
|
7
|
+
data.tar.gz: 5518af92641a14e47ba3bc552bf9e3da25ece970b479ac2e5708fe868eebbb6571b4725b22e8b0374eeb0f0215d550e11054ccb4e7a1883bc8d286fa9df51677
|
data/.reek.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
---
|
2
|
+
detectors:
|
3
|
+
|
4
|
+
DuplicateMethodCall:
|
5
|
+
exclude:
|
6
|
+
- 'PhcStringFormat::PhcString#self.parse'
|
7
|
+
FeatureEnvy:
|
8
|
+
exclude:
|
9
|
+
- 'PhcStringFormat::PhcString#parse_params'
|
10
|
+
|
11
|
+
LongParameterList:
|
12
|
+
max_params: 6
|
13
|
+
overrides:
|
14
|
+
initialize:
|
15
|
+
max_params: 6
|
16
|
+
|
17
|
+
TooManyStatements:
|
18
|
+
max_statements: 10
|
19
|
+
|
20
|
+
TooManyInstanceVariables:
|
21
|
+
max_instance_variables: 6
|
22
|
+
|
23
|
+
UncommunicativeModuleName:
|
24
|
+
accept:
|
25
|
+
- B64
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- bin/*
|
4
|
+
- pkg/*
|
5
|
+
- tmp/**/*
|
6
|
+
- lib/*/version.rb
|
7
|
+
- spec/spec_helper.rb
|
8
|
+
- Gemfile
|
9
|
+
- '*.gemspec'
|
10
|
+
- Rakefile
|
11
|
+
|
12
|
+
Metrics/AbcSize:
|
13
|
+
Max: 20
|
14
|
+
|
15
|
+
Metrics/BlockLength:
|
16
|
+
Exclude:
|
17
|
+
- 'spec/**/*'
|
18
|
+
|
19
|
+
Metrics/CyclomaticComplexity:
|
20
|
+
Max: 10
|
21
|
+
|
22
|
+
Metrics/LineLength:
|
23
|
+
Max: 110
|
24
|
+
|
25
|
+
Metrics/MethodLength:
|
26
|
+
Max: 15
|
27
|
+
|
28
|
+
Metrics/ParameterLists:
|
29
|
+
Max: 6
|
30
|
+
|
31
|
+
Metrics/PerceivedComplexity:
|
32
|
+
Max: 10
|
data/Gemfile
CHANGED
@@ -4,3 +4,7 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
|
4
4
|
|
5
5
|
# Specify your gem's dependencies in phc_string_format.gemspec
|
6
6
|
gemspec
|
7
|
+
|
8
|
+
gem "rubocop", "~> 0.58.2", require: false, :groups => [:development, :test]
|
9
|
+
|
10
|
+
gem "reek", "~> 5.0", require: false, :groups => [:development, :test]
|
data/Gemfile.lock
CHANGED
@@ -1,22 +1,47 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
phc_string_format (0.3.
|
4
|
+
phc_string_format (0.3.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
+
ast (2.4.0)
|
10
|
+
axiom-types (0.1.1)
|
11
|
+
descendants_tracker (~> 0.0.4)
|
12
|
+
ice_nine (~> 0.11.0)
|
13
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
9
14
|
byebug (10.0.2)
|
15
|
+
codeclimate-engine-rb (0.4.1)
|
16
|
+
virtus (~> 1.0)
|
10
17
|
coderay (1.1.2)
|
18
|
+
coercible (1.0.0)
|
19
|
+
descendants_tracker (~> 0.0.1)
|
20
|
+
descendants_tracker (0.0.4)
|
21
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
11
22
|
diff-lcs (1.3)
|
23
|
+
equalizer (0.0.11)
|
24
|
+
ice_nine (0.11.2)
|
25
|
+
jaro_winkler (1.5.1)
|
26
|
+
kwalify (0.7.2)
|
12
27
|
method_source (0.9.0)
|
28
|
+
parallel (1.12.1)
|
29
|
+
parser (2.5.1.2)
|
30
|
+
ast (~> 2.4.0)
|
31
|
+
powerpack (0.1.2)
|
13
32
|
pry (0.11.3)
|
14
33
|
coderay (~> 1.1.0)
|
15
34
|
method_source (~> 0.9.0)
|
16
35
|
pry-byebug (3.6.0)
|
17
36
|
byebug (~> 10.0)
|
18
37
|
pry (~> 0.10)
|
38
|
+
rainbow (3.0.0)
|
19
39
|
rake (10.5.0)
|
40
|
+
reek (5.0.2)
|
41
|
+
codeclimate-engine-rb (~> 0.4.0)
|
42
|
+
kwalify (~> 0.7.0)
|
43
|
+
parser (>= 2.5.0.0, < 2.6, != 2.5.1.1)
|
44
|
+
rainbow (>= 2.0, < 4.0)
|
20
45
|
rspec (3.7.0)
|
21
46
|
rspec-core (~> 3.7.0)
|
22
47
|
rspec-expectations (~> 3.7.0)
|
@@ -30,6 +55,22 @@ GEM
|
|
30
55
|
diff-lcs (>= 1.2.0, < 2.0)
|
31
56
|
rspec-support (~> 3.7.0)
|
32
57
|
rspec-support (3.7.1)
|
58
|
+
rubocop (0.58.2)
|
59
|
+
jaro_winkler (~> 1.5.1)
|
60
|
+
parallel (~> 1.10)
|
61
|
+
parser (>= 2.5, != 2.5.1.1)
|
62
|
+
powerpack (~> 0.1)
|
63
|
+
rainbow (>= 2.2.2, < 4.0)
|
64
|
+
ruby-progressbar (~> 1.7)
|
65
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
66
|
+
ruby-progressbar (1.9.0)
|
67
|
+
thread_safe (0.3.6)
|
68
|
+
unicode-display_width (1.4.0)
|
69
|
+
virtus (1.0.5)
|
70
|
+
axiom-types (~> 0.1)
|
71
|
+
coercible (~> 1.0)
|
72
|
+
descendants_tracker (~> 0.0, >= 0.0.3)
|
73
|
+
equalizer (~> 0.0, >= 0.0.9)
|
33
74
|
|
34
75
|
PLATFORMS
|
35
76
|
ruby
|
@@ -39,7 +80,9 @@ DEPENDENCIES
|
|
39
80
|
phc_string_format!
|
40
81
|
pry-byebug (~> 3.6)
|
41
82
|
rake (~> 10.0)
|
83
|
+
reek (~> 5.0)
|
42
84
|
rspec (~> 3.0)
|
85
|
+
rubocop (~> 0.58.2)
|
43
86
|
|
44
87
|
BUNDLED WITH
|
45
88
|
1.16.2
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
[![Known Vulnerabilities](https://snyk.io/test/github/naokikimura/phc_string_format/badge.svg?targetFile=Gemfile.lock)](https://snyk.io/test/github/naokikimura/phc_string_format?targetFile=Gemfile.lock)
|
6
6
|
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/cbcb6fa3556447a4af16980f3cc6f1eb)](https://app.codacy.com/app/naokikimura/phc_string_format?utm_source=github.com&utm_medium=referral&utm_content=naokikimura/phc_string_format&utm_campaign=badger)
|
7
7
|
|
8
|
-
|
8
|
+
PHC string format implemented by Ruby
|
9
9
|
|
10
10
|
## Installation
|
11
11
|
|
@@ -25,7 +25,20 @@ Or install it yourself as:
|
|
25
25
|
|
26
26
|
## Usage
|
27
27
|
|
28
|
-
|
28
|
+
```ruby
|
29
|
+
require 'phc_string_format'
|
30
|
+
|
31
|
+
encrypted_password = '$argon2i$v=19$m=4096,t=3,p=1$IfH5R3O3r3501DfGnGr2rw$DfQ8Hv9R2eF2uBs1dR99IGjVjDl/rpkJIkaNyZ1g3pk'
|
32
|
+
|
33
|
+
# parse
|
34
|
+
phc_string_params = PhcStringFormat::Formatter.parse(encrypted_password)
|
35
|
+
# => {:id=>"argon2i", :version=>19, :params=>{"m"=>4096, "t"=>3, "p"=>1}, :salt=>"!\xF1\xF9Gs\xB7\xAF~t\xD47\xC6\x9Cj\xF6\xAF", :hash=>"\r\xF4<\x1E\xFFQ\xD9\xE1v\xB8\e5u\x1F} h\xD5\x8C9\x7F\xAE\x99\t\"F\x8D\xC9\x9D`\xDE\x99"}
|
36
|
+
|
37
|
+
# format
|
38
|
+
password_hash = PhcStringFormat::Formatter.format(phc_string_params)
|
39
|
+
|
40
|
+
password_hash == phc_string_format
|
41
|
+
```
|
29
42
|
|
30
43
|
## Development
|
31
44
|
|
data/lib/phc_string_format.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'phc_string_format/b64'
|
2
|
+
require 'phc_string_format/formatter'
|
3
|
+
require 'phc_string_format/phc_string'
|
4
|
+
require 'phc_string_format/version'
|
3
5
|
|
4
6
|
#
|
5
7
|
# PHC string format implemented by Ruby
|
@@ -8,59 +10,9 @@ require "base64"
|
|
8
10
|
# $<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]]
|
9
11
|
# ```
|
10
12
|
#
|
13
|
+
# See:
|
14
|
+
# - https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md
|
15
|
+
# - https://github.com/P-H-C/phc-string-format/pull/4
|
16
|
+
#
|
11
17
|
module PhcStringFormat
|
12
|
-
module Formatter
|
13
|
-
def self.format(id:, version: nil, params: {}, salt: '', hash: '', hint: {salt: {encoding: 'base64'}})
|
14
|
-
raise ArgumentError.new, 'id is required' if id.nil?
|
15
|
-
raise ArgumentError.new, 'hash needs salt' if (salt.nil? || salt.empty?) && !(hash.nil? || hash.empty?)
|
16
|
-
|
17
|
-
elements = [
|
18
|
-
id,
|
19
|
-
("v=#{version}" if version),
|
20
|
-
(params.map{|e| e.join '='}.join(',') if params),
|
21
|
-
hint.dig(:salt, :encoding) == '7bit' ? salt : short_strict_encode64(salt),
|
22
|
-
short_strict_encode64(hash)
|
23
|
-
]
|
24
|
-
"$#{elements.select{|e| !(e.nil? || e.empty?)}.join('$')}"
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.parse(string, pick: nil ,hint: {salt: {encoding: 'base64'}})
|
28
|
-
pick = [:id, :version, :params, :salt, :hash] unless pick
|
29
|
-
elements = string.split(/\$/, 6)
|
30
|
-
elements.shift
|
31
|
-
id = shift_and_parse elements, pick.include?(:id), &-> (e) { e }
|
32
|
-
version = shift_and_parse(elements, pick.include?(:version), &@@parse_version) if (elements.first || '').start_with?('v=')
|
33
|
-
params = shift_and_parse(elements, pick.include?(:params), &@@parse_parameter_string) if (elements.first || '').include?('=')
|
34
|
-
salt = shift_and_parse elements, pick.include?(:salt), &-> (e) {
|
35
|
-
hint.dig(:salt, :encoding) == '7bit' ? e : short_strict_decode64(e)
|
36
|
-
}
|
37
|
-
hash = shift_and_parse elements, pick.include?(:hash), &-> (e) { short_strict_decode64(e) }
|
38
|
-
{id: id, version: version, params: params, salt: salt, hash: hash}.select {|_,v| v}
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.shift_and_parse(elements, picks, &proc)
|
42
|
-
element = elements.shift
|
43
|
-
proc.call(element) if picks
|
44
|
-
end
|
45
|
-
|
46
|
-
@@parse_version = -> (string) {
|
47
|
-
@@parse_parameter_string.call(string)['v']
|
48
|
-
}
|
49
|
-
|
50
|
-
@@parse_parameter_string = -> (string) {
|
51
|
-
string.split(/,/).map {|e| e.split '='}.each_with_object({}){|e, h| k, v = e; h[k] = (/\A-?\d+(.\d+)?\Z/.match(v) ? v.to_i : v)}
|
52
|
-
}
|
53
|
-
|
54
|
-
def self.short_strict_encode64(bin)
|
55
|
-
return nil unless bin
|
56
|
-
Base64.strict_encode64(bin).delete('=')
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.short_strict_decode64(bin)
|
60
|
-
return nil unless bin
|
61
|
-
Base64.strict_decode64(bin + '=' * (-bin.size % 4))
|
62
|
-
end
|
63
|
-
|
64
|
-
private_class_method :short_strict_encode64, :short_strict_decode64
|
65
|
-
end
|
66
18
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module PhcStringFormat
|
4
|
+
#
|
5
|
+
# Implementation of B64
|
6
|
+
#
|
7
|
+
# See:
|
8
|
+
# - https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md#b64
|
9
|
+
#
|
10
|
+
module B64
|
11
|
+
def self.encode(bin)
|
12
|
+
return nil unless bin
|
13
|
+
Base64.strict_encode64(bin).delete('=')
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.decode(bin)
|
17
|
+
return nil unless bin
|
18
|
+
Base64.strict_decode64(bin + '=' * (-bin.size % 4))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module PhcStringFormat
|
2
|
+
#
|
3
|
+
# Formatter for stringifying and parsing PHC-string-format.
|
4
|
+
#
|
5
|
+
module Formatter
|
6
|
+
def self.format(**kwargs)
|
7
|
+
PhcString.create(kwargs).to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.parse(string, hint: {}, pick: nil)
|
11
|
+
PhcString.parse(string, hint: hint).to_h(pick)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module PhcStringFormat
|
2
|
+
#
|
3
|
+
# Parser for parsing PHC-string-format.
|
4
|
+
#
|
5
|
+
class PhcString
|
6
|
+
def self.parse(string, hint: {})
|
7
|
+
string ||= ''
|
8
|
+
elements = string.split(/\$/, 6)
|
9
|
+
elements.shift
|
10
|
+
id = elements.shift
|
11
|
+
version = elements.shift if (elements.first || '').start_with?('v=')
|
12
|
+
params = elements.shift if (elements.first || '').include?('=')
|
13
|
+
salt = elements.shift
|
14
|
+
hash = elements.shift
|
15
|
+
PhcString.new(id, version, params, salt, hash, hint)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.create(id:, version: nil, params: {}, salt: '', hash: '', hint: {})
|
19
|
+
PhcString.new(
|
20
|
+
id,
|
21
|
+
("v=#{version}" if version),
|
22
|
+
(params.map { |entry| entry.join '=' }.join(',') if params),
|
23
|
+
hint.dig(:salt, :encoding) == '7bit' ? salt : B64.encode(salt),
|
24
|
+
B64.encode(hash),
|
25
|
+
hint
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(id, version_string, params_string, encoded_salt, encoded_hash, hint)
|
30
|
+
raise ArgumentError.new, 'id is required' unless id
|
31
|
+
if (!encoded_salt || encoded_salt.empty?) && !(!encoded_hash || encoded_hash.empty?)
|
32
|
+
raise ArgumentError.new, 'hash needs salt'
|
33
|
+
end
|
34
|
+
|
35
|
+
@id = id
|
36
|
+
@version_string = version_string
|
37
|
+
@params_string = params_string
|
38
|
+
@encoded_salt = encoded_salt
|
39
|
+
@encoded_hash = encoded_hash
|
40
|
+
@hint = hint
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
'$' + [
|
45
|
+
@id,
|
46
|
+
@version_string,
|
47
|
+
@params_string,
|
48
|
+
@encoded_salt,
|
49
|
+
@encoded_hash
|
50
|
+
].reject { |element| !element || element.empty? }.join('$')
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_h(pick = nil)
|
54
|
+
pick ||= %i[id version params salt hash]
|
55
|
+
{
|
56
|
+
id: (@id if pick.include?(:id)),
|
57
|
+
version: (parse_version(@version_string) if pick.include?(:version)),
|
58
|
+
params: (parse_params(@params_string) if pick.include?(:params)),
|
59
|
+
salt:
|
60
|
+
if pick.include?(:salt)
|
61
|
+
@hint.dig(:salt, :encoding) == '7bit' ? e : B64.decode(@encoded_salt)
|
62
|
+
end,
|
63
|
+
hash: (B64.decode(@encoded_hash) if pick.include?(:hash))
|
64
|
+
}.select { |_, value| value }
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def parse_version(version_string)
|
70
|
+
parse_params(version_string)['v']
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_params(params_string)
|
74
|
+
mapper = ->(param) { param.split '=' }
|
75
|
+
reducer = lambda do |param, params|
|
76
|
+
name, value = param
|
77
|
+
params[name] = value =~ /\A-?\d+(.\d+)?\Z/ ? value.to_i : value
|
78
|
+
end
|
79
|
+
params_string ||= ''
|
80
|
+
params_string.split(/,/).map(&mapper).each_with_object({}, &reducer)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phc_string_format
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- naokikimura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -74,7 +74,9 @@ extensions: []
|
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
76
|
- ".gitignore"
|
77
|
+
- ".reek.yml"
|
77
78
|
- ".rspec"
|
79
|
+
- ".rubocop.yml"
|
78
80
|
- ".travis.yml"
|
79
81
|
- CODE_OF_CONDUCT.md
|
80
82
|
- Gemfile
|
@@ -85,6 +87,9 @@ files:
|
|
85
87
|
- bin/console
|
86
88
|
- bin/setup
|
87
89
|
- lib/phc_string_format.rb
|
90
|
+
- lib/phc_string_format/b64.rb
|
91
|
+
- lib/phc_string_format/formatter.rb
|
92
|
+
- lib/phc_string_format/phc_string.rb
|
88
93
|
- lib/phc_string_format/version.rb
|
89
94
|
- phc_string_format.gemspec
|
90
95
|
homepage: https://github.com/naokikimura/phc_string_format
|
@@ -109,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
114
|
version: '0'
|
110
115
|
requirements: []
|
111
116
|
rubyforge_project:
|
112
|
-
rubygems_version: 2.
|
117
|
+
rubygems_version: 2.7.6
|
113
118
|
signing_key:
|
114
119
|
specification_version: 4
|
115
120
|
summary: PHC string format implemented by Ruby.
|