-
Notifications
You must be signed in to change notification settings - Fork 636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
V2 SHA and MD5 crypto providers #698
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
1e7bcfb
Fix typo in CONTRINBUTING.md
08b04bc
Add V2 crypto providers for SHA* and MD5 encryption methods. Fixes or…
0637d62
Add CryptoProviders::V2 note to Changelog
266f9c4
Change V2 crypto provider naming scheme to, for example, MD5::V2 from…
3e2f4f0
Assert specified hash values in SHA* (V1) tests. Add MD5 test.
2579461
fixup! Add CryptoProviders::V2 note to Changelog
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# frozen_string_literal: true | ||
|
||
require "digest/md5" | ||
|
||
module Authlogic | ||
module CryptoProviders | ||
class MD5 | ||
# A poor choice. There are known attacks against this algorithm. | ||
class V2 | ||
class << self | ||
attr_accessor :join_token | ||
|
||
# The number of times to loop through the encryption. | ||
def stretches | ||
@stretches ||= 1 | ||
end | ||
attr_writer :stretches | ||
|
||
# Turns your raw password into a MD5 hash. | ||
def encrypt(*tokens) | ||
digest = tokens.flatten.join(join_token) | ||
stretches.times { digest = Digest::MD5.digest(digest) } | ||
digest.unpack("H*")[0] | ||
end | ||
|
||
# Does the crypted password match the tokens? Uses the same tokens that | ||
# were used to encrypt. | ||
def matches?(crypted, *tokens) | ||
encrypt(*tokens) == crypted | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# frozen_string_literal: true | ||
|
||
require "digest/sha1" | ||
|
||
module Authlogic | ||
module CryptoProviders | ||
class Sha1 | ||
# A poor choice. There are known attacks against this algorithm. | ||
class V2 | ||
class << self | ||
def join_token | ||
@join_token ||= "--" | ||
end | ||
attr_writer :join_token | ||
|
||
# The number of times to loop through the encryption. | ||
def stretches | ||
@stretches ||= 10 | ||
end | ||
attr_writer :stretches | ||
|
||
# Turns your raw password into a Sha1 hash. | ||
def encrypt(*tokens) | ||
tokens = tokens.flatten | ||
digest = tokens.shift | ||
stretches.times do | ||
digest = Digest::SHA1.digest([digest, *tokens].join(join_token)) | ||
end | ||
digest.unpack("H*")[0] | ||
end | ||
|
||
# Does the crypted password match the tokens? Uses the same tokens that | ||
# were used to encrypt. | ||
def matches?(crypted, *tokens) | ||
encrypt(*tokens) == crypted | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# frozen_string_literal: true | ||
|
||
require "digest/sha2" | ||
|
||
module Authlogic | ||
# The acts_as_authentic method has a crypto_provider option. This allows you | ||
# to use any type of encryption you like. Just create a class with a class | ||
# level encrypt and matches? method. See example below. | ||
# | ||
# === Example | ||
# | ||
# class MyAwesomeEncryptionMethod | ||
# def self.encrypt(*tokens) | ||
# # the tokens passed will be an array of objects, what type of object | ||
# # is irrelevant, just do what you need to do with them and return a | ||
# # single encrypted string. for example, you will most likely join all | ||
# # of the objects into a single string and then encrypt that string | ||
# end | ||
# | ||
# def self.matches?(crypted, *tokens) | ||
# # return true if the crypted string matches the tokens. Depending on | ||
# # your algorithm you might decrypt the string then compare it to the | ||
# # token, or you might encrypt the tokens and make sure it matches the | ||
# # crypted string, its up to you. | ||
# end | ||
# end | ||
module CryptoProviders | ||
class Sha256 | ||
# = Sha256 | ||
# | ||
# Uses the Sha256 hash algorithm to encrypt passwords. | ||
class V2 | ||
class << self | ||
attr_accessor :join_token | ||
|
||
# The number of times to loop through the encryption. | ||
def stretches | ||
@stretches ||= 20 | ||
end | ||
attr_writer :stretches | ||
|
||
# Turns your raw password into a Sha256 hash. | ||
def encrypt(*tokens) | ||
digest = tokens.flatten.join(join_token) | ||
stretches.times { digest = Digest::SHA256.digest(digest) } | ||
digest.unpack("H*")[0] | ||
end | ||
|
||
# Does the crypted password match the tokens? Uses the same tokens that | ||
# were used to encrypt. | ||
def matches?(crypted, *tokens) | ||
encrypt(*tokens) == crypted | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# frozen_string_literal: true | ||
|
||
require "digest/sha2" | ||
|
||
module Authlogic | ||
module CryptoProviders | ||
class Sha512 | ||
# SHA-512 does not have any practical known attacks against it. However, | ||
# there are better choices. We recommend transitioning to a more secure, | ||
# adaptive hashing algorithm, like scrypt. | ||
class V2 | ||
class << self | ||
attr_accessor :join_token | ||
|
||
# The number of times to loop through the encryption. | ||
def stretches | ||
@stretches ||= 20 | ||
end | ||
attr_writer :stretches | ||
|
||
# Turns your raw password into a Sha512 hash. | ||
def encrypt(*tokens) | ||
digest = tokens.flatten.join(join_token) | ||
stretches.times do | ||
digest = Digest::SHA512.digest(digest) | ||
end | ||
digest.unpack("H*")[0] | ||
end | ||
|
||
# Does the crypted password match the tokens? Uses the same tokens that | ||
# were used to encrypt. | ||
def matches?(crypted, *tokens) | ||
encrypt(*tokens) == crypted | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# frozen_string_literal: true | ||
|
||
require "test_helper" | ||
|
||
module CryptoProviderTest | ||
module MD5 | ||
class V2Test < ActiveSupport::TestCase | ||
def setup | ||
@default_stretches = Authlogic::CryptoProviders::MD5::V2.stretches | ||
end | ||
|
||
def teardown | ||
Authlogic::CryptoProviders::MD5::V2.stretches = @default_stretches | ||
end | ||
|
||
def test_encrypt | ||
password = "test" | ||
salt = "7e3041ebc2fc05a40c60028e2c4901a81035d3cd" | ||
expected_digest = "3d16884295a68fec30a2ae7ff0634b1e" | ||
|
||
digest = Authlogic::CryptoProviders::MD5::V2.encrypt(password, salt) | ||
|
||
assert_equal digest, expected_digest | ||
end | ||
|
||
def test_encrypt_with_3_stretches | ||
Authlogic::CryptoProviders::MD5::V2.stretches = 3 | ||
password = "test" | ||
salt = "7e3041ebc2fc05a40c60028e2c4901a81035d3cd" | ||
expected_digest = "da62ac8b983606f684cea0b93a558283" | ||
|
||
digest = Authlogic::CryptoProviders::MD5::V2.encrypt(password, salt) | ||
|
||
assert_equal digest, expected_digest | ||
end | ||
|
||
def test_matches | ||
password = "test" | ||
salt = "7e3041ebc2fc05a40c60028e2c4901a81035d3cd" | ||
expected_digest = "3d16884295a68fec30a2ae7ff0634b1e" | ||
|
||
assert Authlogic::CryptoProviders::MD5::V2.matches?(expected_digest, password, salt) | ||
end | ||
|
||
def test_not_matches | ||
password = "test" | ||
salt = "7e3041ebc2fc05a40c60028e2c4901a81035d3cd" | ||
bad_digest = "12345" | ||
|
||
assert !Authlogic::CryptoProviders::MD5::V2.matches?(bad_digest, password, salt) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# frozen_string_literal: true | ||
|
||
require "test_helper" | ||
|
||
module CryptoProviderTest | ||
class MD5Test < ActiveSupport::TestCase | ||
def setup | ||
@default_stretches = Authlogic::CryptoProviders::MD5.stretches | ||
end | ||
|
||
def teardown | ||
Authlogic::CryptoProviders::MD5.stretches = @default_stretches | ||
end | ||
|
||
def test_encrypt | ||
password = "test" | ||
salt = "7e3041ebc2fc05a40c60028e2c4901a81035d3cd" | ||
expected_digest = "3d16884295a68fec30a2ae7ff0634b1e" | ||
|
||
digest = Authlogic::CryptoProviders::MD5.encrypt(password, salt) | ||
|
||
assert_equal digest, expected_digest | ||
end | ||
|
||
def test_encrypt_with_3_stretches | ||
Authlogic::CryptoProviders::MD5.stretches = 3 | ||
password = "test" | ||
salt = "7e3041ebc2fc05a40c60028e2c4901a81035d3cd" | ||
expected_digest = "9ac3a3a2e68f822f3482cbea3cbed9a3" | ||
|
||
digest = Authlogic::CryptoProviders::MD5.encrypt(password, salt) | ||
|
||
assert_equal digest, expected_digest | ||
end | ||
|
||
def test_matches | ||
password = "test" | ||
salt = "7e3041ebc2fc05a40c60028e2c4901a81035d3cd" | ||
expected_digest = "3d16884295a68fec30a2ae7ff0634b1e" | ||
|
||
assert Authlogic::CryptoProviders::MD5.matches?(expected_digest, password, salt) | ||
end | ||
|
||
def test_not_matches | ||
password = "test" | ||
salt = "7e3041ebc2fc05a40c60028e2c4901a81035d3cd" | ||
bad_digest = "12345" | ||
|
||
assert !Authlogic::CryptoProviders::MD5.matches?(bad_digest, password, salt) | ||
end | ||
end | ||
end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow
each_cons
is perfect for this. Nice!