mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:27:42 +00:00
feat(crypto): use passwap for machine and app secrets (#7657)
* feat(crypto): use passwap for machine and app secrets * fix command package tests * add hash generator command test * naming convention, fix query tests * rename PasswordHasher and cleanup start commands * add reducer tests * fix intergration tests, cleanup old config * add app secret unit tests * solve setup panics * fix push of updated events * add missing event translations * update documentation * solve linter errors * remove nolint:SA1019 as it doesn't seem to help anyway * add nolint to deprecated filter usage * update users migration version * remove unused ClientSecret from APIConfigChangedEvent --------- Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var _ HashAlgorithm = (*BCrypt)(nil)
|
||||
|
||||
type BCrypt struct {
|
||||
cost int
|
||||
}
|
||||
|
||||
func NewBCrypt(cost int) *BCrypt {
|
||||
return &BCrypt{cost: cost}
|
||||
}
|
||||
|
||||
func (b *BCrypt) Algorithm() string {
|
||||
return "bcrypt"
|
||||
}
|
||||
|
||||
func (b *BCrypt) Hash(value []byte) ([]byte, error) {
|
||||
return bcrypt.GenerateFromPassword(value, b.cost)
|
||||
}
|
||||
|
||||
func (b *BCrypt) CompareHash(hashed, value []byte) error {
|
||||
return bcrypt.CompareHashAndPassword(hashed, value)
|
||||
}
|
@@ -26,7 +26,7 @@ type GeneratorConfig struct {
|
||||
type Generator interface {
|
||||
Length() uint
|
||||
Expiry() time.Duration
|
||||
Alg() Crypto
|
||||
Alg() EncryptionAlgorithm
|
||||
Runes() []rune
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ type encryptionGenerator struct {
|
||||
alg EncryptionAlgorithm
|
||||
}
|
||||
|
||||
func (g *encryptionGenerator) Alg() Crypto {
|
||||
func (g *encryptionGenerator) Alg() EncryptionAlgorithm {
|
||||
return g.alg
|
||||
}
|
||||
|
||||
@@ -64,22 +64,30 @@ func NewEncryptionGenerator(config GeneratorConfig, algorithm EncryptionAlgorith
|
||||
}
|
||||
}
|
||||
|
||||
type hashGenerator struct {
|
||||
type HashGenerator struct {
|
||||
generator
|
||||
alg HashAlgorithm
|
||||
hasher *Hasher
|
||||
}
|
||||
|
||||
func (g *hashGenerator) Alg() Crypto {
|
||||
return g.alg
|
||||
}
|
||||
|
||||
func NewHashGenerator(config GeneratorConfig, algorithm HashAlgorithm) Generator {
|
||||
return &hashGenerator{
|
||||
func NewHashGenerator(config GeneratorConfig, hasher *Hasher) *HashGenerator {
|
||||
return &HashGenerator{
|
||||
newGenerator(config),
|
||||
algorithm,
|
||||
hasher,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *HashGenerator) NewCode() (encoded, plain string, err error) {
|
||||
plain, err = GenerateRandomString(g.Length(), g.Runes())
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
encoded, err = g.hasher.Hash(plain)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return encoded, plain, nil
|
||||
}
|
||||
|
||||
func newGenerator(config GeneratorConfig) generator {
|
||||
var runes []rune
|
||||
if config.IncludeLowerLetters {
|
||||
@@ -120,21 +128,11 @@ func IsCodeExpired(creationDate time.Time, expiry time.Duration) bool {
|
||||
return creationDate.Add(expiry).Before(time.Now().UTC())
|
||||
}
|
||||
|
||||
func VerifyCode(creationDate time.Time, expiry time.Duration, cryptoCode *CryptoValue, verificationCode string, g Generator) error {
|
||||
return VerifyCodeWithAlgorithm(creationDate, expiry, cryptoCode, verificationCode, g.Alg())
|
||||
}
|
||||
|
||||
func VerifyCodeWithAlgorithm(creationDate time.Time, expiry time.Duration, cryptoCode *CryptoValue, verificationCode string, algorithm Crypto) error {
|
||||
func VerifyCode(creationDate time.Time, expiry time.Duration, cryptoCode *CryptoValue, verificationCode string, algorithm EncryptionAlgorithm) error {
|
||||
if IsCodeExpired(creationDate, expiry) {
|
||||
return zerrors.ThrowPreconditionFailed(nil, "CODE-QvUQ4P", "Errors.User.Code.Expired")
|
||||
}
|
||||
switch alg := algorithm.(type) {
|
||||
case EncryptionAlgorithm:
|
||||
return verifyEncryptedCode(cryptoCode, verificationCode, alg)
|
||||
case HashAlgorithm:
|
||||
return verifyHashedCode(cryptoCode, verificationCode, alg)
|
||||
}
|
||||
return zerrors.ThrowInvalidArgument(nil, "CODE-fW2gNa", "Errors.User.Code.GeneratorAlgNotSupported")
|
||||
return verifyEncryptedCode(cryptoCode, verificationCode, algorithm)
|
||||
}
|
||||
|
||||
func GenerateRandomString(length uint, chars []rune) (string, error) {
|
||||
@@ -173,10 +171,3 @@ func verifyEncryptedCode(cryptoCode *CryptoValue, verificationCode string, alg E
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyHashedCode(cryptoCode *CryptoValue, verificationCode string, alg HashAlgorithm) error {
|
||||
if cryptoCode == nil {
|
||||
return zerrors.ThrowInvalidArgument(nil, "CRYPT-2q3r", "cryptoCode must not be nil")
|
||||
}
|
||||
return CompareHash(cryptoCode, []byte(verificationCode), alg)
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@
|
||||
//
|
||||
// mockgen -source code.go -destination ./code_mock.go -package crypto
|
||||
//
|
||||
|
||||
// Package crypto is a generated GoMock package.
|
||||
package crypto
|
||||
|
||||
@@ -39,10 +40,10 @@ func (m *MockGenerator) EXPECT() *MockGeneratorMockRecorder {
|
||||
}
|
||||
|
||||
// Alg mocks base method.
|
||||
func (m *MockGenerator) Alg() Crypto {
|
||||
func (m *MockGenerator) Alg() EncryptionAlgorithm {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Alg")
|
||||
ret0, _ := ret[0].(Crypto)
|
||||
ret0, _ := ret[0].(EncryptionAlgorithm)
|
||||
return ret0
|
||||
}
|
||||
|
||||
|
@@ -60,32 +60,13 @@ func createMockEncryptionAlgorithm(ctrl *gomock.Controller, encryptFunction func
|
||||
return mCrypto
|
||||
}
|
||||
|
||||
func CreateMockHashAlg(ctrl *gomock.Controller) HashAlgorithm {
|
||||
mCrypto := NewMockHashAlgorithm(ctrl)
|
||||
mCrypto.EXPECT().Algorithm().AnyTimes().Return("hash")
|
||||
mCrypto.EXPECT().Hash(gomock.Any()).AnyTimes().DoAndReturn(
|
||||
func(code []byte) ([]byte, error) {
|
||||
return code, nil
|
||||
},
|
||||
)
|
||||
mCrypto.EXPECT().CompareHash(gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
|
||||
func(hashed, comparer []byte) error {
|
||||
if string(hashed) != string(comparer) {
|
||||
return zerrors.ThrowInternal(nil, "id", "invalid")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
return mCrypto
|
||||
}
|
||||
|
||||
func createMockCrypto(t *testing.T) Crypto {
|
||||
mCrypto := NewMockCrypto(gomock.NewController(t))
|
||||
func createMockCrypto(t *testing.T) EncryptionAlgorithm {
|
||||
mCrypto := NewMockEncryptionAlgorithm(gomock.NewController(t))
|
||||
mCrypto.EXPECT().Algorithm().AnyTimes().Return("crypto")
|
||||
return mCrypto
|
||||
}
|
||||
|
||||
func createMockGenerator(t *testing.T, crypto Crypto) Generator {
|
||||
func createMockGenerator(t *testing.T, crypto EncryptionAlgorithm) Generator {
|
||||
mGenerator := NewMockGenerator(gomock.NewController(t))
|
||||
mGenerator.EXPECT().Alg().AnyTimes().Return(crypto)
|
||||
return mGenerator
|
||||
|
@@ -102,25 +102,10 @@ func TestVerifyCode(t *testing.T) {
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"hash alg ok",
|
||||
args{
|
||||
creationDate: time.Now(),
|
||||
expiry: 5 * time.Minute,
|
||||
cryptoCode: &CryptoValue{
|
||||
CryptoType: TypeHash,
|
||||
Algorithm: "hash",
|
||||
Crypted: []byte("code"),
|
||||
},
|
||||
verificationCode: "code",
|
||||
g: createMockGenerator(t, CreateMockHashAlg(gomock.NewController(t))),
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := VerifyCode(tt.args.creationDate, tt.args.expiry, tt.args.cryptoCode, tt.args.verificationCode, tt.args.g); (err != nil) != tt.wantErr {
|
||||
if err := VerifyCode(tt.args.creationDate, tt.args.expiry, tt.args.cryptoCode, tt.args.verificationCode, tt.args.g.Alg()); (err != nil) != tt.wantErr {
|
||||
t.Errorf("VerifyCode() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
@@ -222,85 +207,3 @@ func Test_verifyEncryptedCode(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_verifyHashedCode(t *testing.T) {
|
||||
type args struct {
|
||||
cryptoCode *CryptoValue
|
||||
verificationCode string
|
||||
alg HashAlgorithm
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
|
||||
{
|
||||
"nil error",
|
||||
args{
|
||||
cryptoCode: nil,
|
||||
verificationCode: "",
|
||||
alg: CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"wrong cryptotype error",
|
||||
args{
|
||||
cryptoCode: &CryptoValue{
|
||||
CryptoType: TypeEncryption,
|
||||
Crypted: nil,
|
||||
},
|
||||
verificationCode: "",
|
||||
alg: CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"wrong algorithm error",
|
||||
args{
|
||||
cryptoCode: &CryptoValue{
|
||||
CryptoType: TypeHash,
|
||||
Algorithm: "hash2",
|
||||
Crypted: nil,
|
||||
},
|
||||
verificationCode: "",
|
||||
alg: CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"wrong verification code error",
|
||||
args{
|
||||
cryptoCode: &CryptoValue{
|
||||
CryptoType: TypeHash,
|
||||
Algorithm: "hash",
|
||||
Crypted: []byte("code"),
|
||||
},
|
||||
verificationCode: "wrong",
|
||||
alg: CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"verification code ok",
|
||||
args{
|
||||
cryptoCode: &CryptoValue{
|
||||
CryptoType: TypeHash,
|
||||
Algorithm: "hash",
|
||||
Crypted: []byte("code"),
|
||||
},
|
||||
verificationCode: "code",
|
||||
alg: CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := verifyHashedCode(tt.args.cryptoCode, tt.args.verificationCode, tt.args.alg); (err != nil) != tt.wantErr {
|
||||
t.Errorf("verifyHashedCode() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -13,12 +13,8 @@ const (
|
||||
TypeHash // Depcrecated: use [passwap.Swapper] instead
|
||||
)
|
||||
|
||||
type Crypto interface {
|
||||
Algorithm() string
|
||||
}
|
||||
|
||||
type EncryptionAlgorithm interface {
|
||||
Crypto
|
||||
Algorithm() string
|
||||
EncryptionKeyID() string
|
||||
DecryptionKeyIDs() []string
|
||||
Encrypt(value []byte) ([]byte, error)
|
||||
@@ -26,13 +22,6 @@ type EncryptionAlgorithm interface {
|
||||
DecryptString(hashed []byte, keyID string) (string, error)
|
||||
}
|
||||
|
||||
// Depcrecated: use [passwap.Swapper] instead
|
||||
type HashAlgorithm interface {
|
||||
Crypto
|
||||
Hash(value []byte) ([]byte, error)
|
||||
CompareHash(hashed, comparer []byte) error
|
||||
}
|
||||
|
||||
type CryptoValue struct {
|
||||
CryptoType CryptoType
|
||||
Algorithm string
|
||||
@@ -59,14 +48,8 @@ func (c *CryptoValue) Scan(src interface{}) error {
|
||||
|
||||
type CryptoType int
|
||||
|
||||
func Crypt(value []byte, c Crypto) (*CryptoValue, error) {
|
||||
switch alg := c.(type) {
|
||||
case EncryptionAlgorithm:
|
||||
return Encrypt(value, alg)
|
||||
case HashAlgorithm:
|
||||
return Hash(value, alg)
|
||||
}
|
||||
return nil, zerrors.ThrowInternal(nil, "CRYPT-r4IaHZ", "algorithm not supported")
|
||||
func Crypt(value []byte, alg EncryptionAlgorithm) (*CryptoValue, error) {
|
||||
return Encrypt(value, alg)
|
||||
}
|
||||
|
||||
func Encrypt(value []byte, alg EncryptionAlgorithm) (*CryptoValue, error) {
|
||||
@@ -108,33 +91,6 @@ func checkEncryptionAlgorithm(value *CryptoValue, alg EncryptionAlgorithm) error
|
||||
return zerrors.ThrowInvalidArgument(nil, "CRYPT-Kq12vn", "value was encrypted with a different key")
|
||||
}
|
||||
|
||||
func Hash(value []byte, alg HashAlgorithm) (*CryptoValue, error) {
|
||||
hashed, err := alg.Hash(value)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "CRYPT-rBVaJU", "error hashing value")
|
||||
}
|
||||
return &CryptoValue{
|
||||
CryptoType: TypeHash,
|
||||
Algorithm: alg.Algorithm(),
|
||||
Crypted: hashed,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func CompareHash(value *CryptoValue, comparer []byte, alg HashAlgorithm) error {
|
||||
if value.Algorithm != alg.Algorithm() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "CRYPT-HF32f", "value was hashed with a different algorithm")
|
||||
}
|
||||
return alg.CompareHash(value.Crypted, comparer)
|
||||
}
|
||||
|
||||
func FillHash(value []byte, alg HashAlgorithm) *CryptoValue {
|
||||
return &CryptoValue{
|
||||
CryptoType: TypeHash,
|
||||
Algorithm: alg.Algorithm(),
|
||||
Crypted: value,
|
||||
}
|
||||
}
|
||||
|
||||
func CheckToken(alg EncryptionAlgorithm, token string, content string) error {
|
||||
if token == "" {
|
||||
return zerrors.ThrowPermissionDenied(nil, "CRYPTO-Sfefs", "Errors.Intent.InvalidToken")
|
||||
@@ -152,3 +108,12 @@ func CheckToken(alg EncryptionAlgorithm, token string, content string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SecretOrEncodedHash returns the Crypted value from legacy [CryptoValue] if it is not nil.
|
||||
// otherwise it will returns the encoded hash string.
|
||||
func SecretOrEncodedHash(secret *CryptoValue, encoded string) string {
|
||||
if secret != nil {
|
||||
return string(secret.Crypted)
|
||||
}
|
||||
return encoded
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@
|
||||
//
|
||||
// mockgen -source crypto.go -destination ./crypto_mock.go -package crypto
|
||||
//
|
||||
|
||||
// Package crypto is a generated GoMock package.
|
||||
package crypto
|
||||
|
||||
@@ -14,43 +15,6 @@ import (
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockCrypto is a mock of Crypto interface.
|
||||
type MockCrypto struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockCryptoMockRecorder
|
||||
}
|
||||
|
||||
// MockCryptoMockRecorder is the mock recorder for MockCrypto.
|
||||
type MockCryptoMockRecorder struct {
|
||||
mock *MockCrypto
|
||||
}
|
||||
|
||||
// NewMockCrypto creates a new mock instance.
|
||||
func NewMockCrypto(ctrl *gomock.Controller) *MockCrypto {
|
||||
mock := &MockCrypto{ctrl: ctrl}
|
||||
mock.recorder = &MockCryptoMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockCrypto) EXPECT() *MockCryptoMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Algorithm mocks base method.
|
||||
func (m *MockCrypto) Algorithm() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Algorithm")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Algorithm indicates an expected call of Algorithm.
|
||||
func (mr *MockCryptoMockRecorder) Algorithm() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockCrypto)(nil).Algorithm))
|
||||
}
|
||||
|
||||
// MockEncryptionAlgorithm is a mock of EncryptionAlgorithm interface.
|
||||
type MockEncryptionAlgorithm struct {
|
||||
ctrl *gomock.Controller
|
||||
@@ -160,69 +124,3 @@ func (mr *MockEncryptionAlgorithmMockRecorder) EncryptionKeyID() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EncryptionKeyID", reflect.TypeOf((*MockEncryptionAlgorithm)(nil).EncryptionKeyID))
|
||||
}
|
||||
|
||||
// MockHashAlgorithm is a mock of HashAlgorithm interface.
|
||||
type MockHashAlgorithm struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockHashAlgorithmMockRecorder
|
||||
}
|
||||
|
||||
// MockHashAlgorithmMockRecorder is the mock recorder for MockHashAlgorithm.
|
||||
type MockHashAlgorithmMockRecorder struct {
|
||||
mock *MockHashAlgorithm
|
||||
}
|
||||
|
||||
// NewMockHashAlgorithm creates a new mock instance.
|
||||
func NewMockHashAlgorithm(ctrl *gomock.Controller) *MockHashAlgorithm {
|
||||
mock := &MockHashAlgorithm{ctrl: ctrl}
|
||||
mock.recorder = &MockHashAlgorithmMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockHashAlgorithm) EXPECT() *MockHashAlgorithmMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Algorithm mocks base method.
|
||||
func (m *MockHashAlgorithm) Algorithm() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Algorithm")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Algorithm indicates an expected call of Algorithm.
|
||||
func (mr *MockHashAlgorithmMockRecorder) Algorithm() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Algorithm", reflect.TypeOf((*MockHashAlgorithm)(nil).Algorithm))
|
||||
}
|
||||
|
||||
// CompareHash mocks base method.
|
||||
func (m *MockHashAlgorithm) CompareHash(hashed, comparer []byte) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CompareHash", hashed, comparer)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CompareHash indicates an expected call of CompareHash.
|
||||
func (mr *MockHashAlgorithmMockRecorder) CompareHash(hashed, comparer any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CompareHash", reflect.TypeOf((*MockHashAlgorithm)(nil).CompareHash), hashed, comparer)
|
||||
}
|
||||
|
||||
// Hash mocks base method.
|
||||
func (m *MockHashAlgorithm) Hash(value []byte) ([]byte, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Hash", value)
|
||||
ret0, _ := ret[0].([]byte)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Hash indicates an expected call of Hash.
|
||||
func (mr *MockHashAlgorithmMockRecorder) Hash(value any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Hash", reflect.TypeOf((*MockHashAlgorithm)(nil).Hash), value)
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ func (a *alg) Algorithm() string {
|
||||
func TestCrypt(t *testing.T) {
|
||||
type args struct {
|
||||
value []byte
|
||||
c Crypto
|
||||
c EncryptionAlgorithm
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -74,18 +74,6 @@ func TestCrypt(t *testing.T) {
|
||||
&CryptoValue{CryptoType: TypeEncryption, Algorithm: "enc", KeyID: "keyID", Crypted: []byte("test")},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"hash",
|
||||
args{[]byte("test"), &mockHashCrypto{}},
|
||||
&CryptoValue{CryptoType: TypeHash, Algorithm: "hash", Crypted: []byte("test")},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"wrong type",
|
||||
args{[]byte("test"), &alg{}},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -208,66 +196,3 @@ func TestDecryptString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHash(t *testing.T) {
|
||||
type args struct {
|
||||
value []byte
|
||||
c HashAlgorithm
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *CryptoValue
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"ok",
|
||||
args{[]byte("test"), &mockHashCrypto{}},
|
||||
&CryptoValue{CryptoType: TypeHash, Algorithm: "hash", Crypted: []byte("test")},
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := Hash(tt.args.value, tt.args.c)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Hash() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Hash() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareHash(t *testing.T) {
|
||||
type args struct {
|
||||
value *CryptoValue
|
||||
comparer []byte
|
||||
c HashAlgorithm
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"ok",
|
||||
args{&CryptoValue{CryptoType: TypeHash, Algorithm: "hash", Crypted: []byte("test")}, []byte("test"), &mockHashCrypto{}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"wrong",
|
||||
args{&CryptoValue{CryptoType: TypeHash, Algorithm: "hash", Crypted: []byte("test")}, []byte("test2"), &mockHashCrypto{}},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := CompareHash(tt.args.value, tt.args.comparer, tt.args.c); (err != nil) != tt.wantErr {
|
||||
t.Errorf("CompareHash() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -16,12 +16,12 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type PasswordHasher struct {
|
||||
type Hasher struct {
|
||||
*passwap.Swapper
|
||||
Prefixes []string
|
||||
}
|
||||
|
||||
func (h *PasswordHasher) EncodingSupported(encodedHash string) bool {
|
||||
func (h *Hasher) EncodingSupported(encodedHash string) bool {
|
||||
for _, prefix := range h.Prefixes {
|
||||
if strings.HasPrefix(encodedHash, prefix) {
|
||||
return true
|
||||
@@ -54,12 +54,12 @@ const (
|
||||
HashModeSHA512 HashMode = "sha512"
|
||||
)
|
||||
|
||||
type PasswordHashConfig struct {
|
||||
type HashConfig struct {
|
||||
Verifiers []HashName
|
||||
Hasher HasherConfig
|
||||
}
|
||||
|
||||
func (c *PasswordHashConfig) PasswordHasher() (*PasswordHasher, error) {
|
||||
func (c *HashConfig) NewHasher() (*Hasher, error) {
|
||||
verifiers, vPrefixes, err := c.buildVerifiers()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "CRYPT-sahW9", "password hash config invalid")
|
||||
@@ -68,7 +68,7 @@ func (c *PasswordHashConfig) PasswordHasher() (*PasswordHasher, error) {
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "CRYPT-Que4r", "password hash config invalid")
|
||||
}
|
||||
return &PasswordHasher{
|
||||
return &Hasher{
|
||||
Swapper: passwap.NewSwapper(hasher, verifiers...),
|
||||
Prefixes: append(hPrefixes, vPrefixes...),
|
||||
}, nil
|
||||
@@ -105,7 +105,7 @@ var knowVerifiers = map[HashName]prefixVerifier{
|
||||
},
|
||||
}
|
||||
|
||||
func (c *PasswordHashConfig) buildVerifiers() (verifiers []verifier.Verifier, prefixes []string, err error) {
|
||||
func (c *HashConfig) buildVerifiers() (verifiers []verifier.Verifier, prefixes []string, err error) {
|
||||
verifiers = make([]verifier.Verifier, len(c.Verifiers))
|
||||
prefixes = make([]string, 0, len(c.Verifiers)+1)
|
||||
for i, name := range c.Verifiers {
|
||||
|
@@ -49,7 +49,7 @@ func TestPasswordHasher_EncodingSupported(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
h := &PasswordHasher{
|
||||
h := &Hasher{
|
||||
Prefixes: []string{bcrypt.Prefix, argon2.Prefix},
|
||||
}
|
||||
got := h.EncodingSupported(tt.encodedHash)
|
||||
@@ -340,11 +340,11 @@ func TestPasswordHashConfig_PasswordHasher(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &PasswordHashConfig{
|
||||
c := &HashConfig{
|
||||
Verifiers: tt.fields.Verifiers,
|
||||
Hasher: tt.fields.Hasher,
|
||||
}
|
||||
got, err := c.PasswordHasher()
|
||||
got, err := c.NewHasher()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
|
Reference in New Issue
Block a user