diff --git a/models/twofactor.go b/models/twofactor.go index 36ff5db42..526ab917e 100644 --- a/models/twofactor.go +++ b/models/twofactor.go @@ -5,11 +5,15 @@ package models import ( + "crypto/aes" + "crypto/cipher" "crypto/md5" + "crypto/rand" "crypto/subtle" "encoding/base64" + "errors" + "io" - "github.com/Unknwon/com" "github.com/pquerna/otp/totp" "code.gitea.io/gitea/modules/base" @@ -52,7 +56,7 @@ func (t *TwoFactor) getEncryptionKey() []byte { // SetSecret sets the 2FA secret. func (t *TwoFactor) SetSecret(secret string) error { - secretBytes, err := com.AESGCMEncrypt(t.getEncryptionKey(), []byte(secret)) + secretBytes, err := aesEncrypt(t.getEncryptionKey(), []byte(secret)) if err != nil { return err } @@ -66,7 +70,7 @@ func (t *TwoFactor) ValidateTOTP(passcode string) (bool, error) { if err != nil { return false, err } - secret, err := com.AESGCMDecrypt(t.getEncryptionKey(), decodedStoredSecret) + secret, err := aesDecrypt(t.getEncryptionKey(), decodedStoredSecret) if err != nil { return false, err } @@ -74,6 +78,43 @@ func (t *TwoFactor) ValidateTOTP(passcode string) (bool, error) { return totp.Validate(passcode, secretStr), nil } +// aesEncrypt encrypts text and given key with AES. +func aesEncrypt(key, text []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + b := base64.StdEncoding.EncodeToString(text) + ciphertext := make([]byte, aes.BlockSize+len(b)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return nil, err + } + cfb := cipher.NewCFBEncrypter(block, iv) + cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b)) + return ciphertext, nil +} + +// aesDecrypt decrypts text and given key with AES. +func aesDecrypt(key, text []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + if len(text) < aes.BlockSize { + return nil, errors.New("ciphertext too short") + } + iv := text[:aes.BlockSize] + text = text[aes.BlockSize:] + cfb := cipher.NewCFBDecrypter(block, iv) + cfb.XORKeyStream(text, text) + data, err := base64.StdEncoding.DecodeString(string(text)) + if err != nil { + return nil, err + } + return data, nil +} + // NewTwoFactor creates a new two-factor authentication token. func NewTwoFactor(t *TwoFactor) error { err := t.GenerateScratchToken()