-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: md5 plain digest support (#39)
This change adds support for verification of plain md5 digests without salt.
- Loading branch information
Showing
6 changed files
with
129 additions
and
18 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import hashlib | ||
|
||
password = b"password" | ||
|
||
print("MD5PlainHex = `", hashlib.md5(password).hexdigest(), "`", sep="") |
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,36 @@ | ||
// Package md5plain provides verification of | ||
// plain md5 digests of passwords without salt. | ||
// | ||
// Note that md5 is considered cryptographically broken | ||
// and should not be used for new applications. | ||
// This package is only provided for legacy applications | ||
// that wish to migrate away from md5 to newer hashing methods. | ||
package md5plain | ||
|
||
import ( | ||
"crypto/md5" | ||
"crypto/subtle" | ||
"encoding/hex" | ||
"fmt" | ||
|
||
"github.com/zitadel/passwap/verifier" | ||
) | ||
|
||
// Verify an plain md5 digest without salt. | ||
// Digest must be hex encoded. | ||
// | ||
// Note that md5 digests do not have an identifier. | ||
// Therefore it might be that Verify accepts any hex encoded string | ||
// but fails password verification. | ||
func Verify(digest, password string) (verifier.Result, error) { | ||
decoded, err := hex.DecodeString(digest) | ||
if err != nil { | ||
return verifier.Skip, fmt.Errorf("md5plain parse: %w", err) | ||
} | ||
sum := md5.Sum([]byte(password)) | ||
res := subtle.ConstantTimeCompare(sum[:], decoded) | ||
|
||
return verifier.Result(res), nil | ||
} | ||
|
||
var Verifier = verifier.VerifyFunc(Verify) |
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,51 @@ | ||
package md5plain | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/zitadel/passwap/internal/testvalues" | ||
"github.com/zitadel/passwap/verifier" | ||
) | ||
|
||
func TestVerify(t *testing.T) { | ||
type args struct { | ||
hash string | ||
password string | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want verifier.Result | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "decode error", | ||
args: args{"!!!", testvalues.Password}, | ||
want: verifier.Skip, | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "wrong password", | ||
args: args{testvalues.MD5PlainHex, "foobar"}, | ||
want: verifier.Fail, | ||
}, | ||
{ | ||
name: "success", | ||
args: args{testvalues.MD5PlainHex, testvalues.Password}, | ||
want: verifier.OK, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got, err := Verify(tt.args.hash, tt.args.password) | ||
if (err != nil) != tt.wantErr { | ||
t.Errorf("Verify() error = %v, wantErr %v", err, tt.wantErr) | ||
return | ||
} | ||
if !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("Verify() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |