diff options
author | Morgan Bazalgette <git@howl.moe> | 2017-12-31 03:19:42 +0100 |
---|---|---|
committer | Lauris BH <lauris@nix.lv> | 2017-12-31 04:19:42 +0200 |
commit | edce41ae652b278aa938dd8b2208722f3ee6afb4 (patch) | |
tree | 562e0fa206b7f64d64610e23adab42b46800fc88 /models/twofactor.go | |
parent | d2736e268bd6a72cb6c0c1d3de85388541f42284 (diff) | |
download | gitea-edce41ae652b278aa938dd8b2208722f3ee6afb4.tar.gz gitea-edce41ae652b278aa938dd8b2208722f3ee6afb4.zip |
go back to using CFB for AES decryption/encryption for 2FA (#3274)
Diffstat (limited to 'models/twofactor.go')
-rw-r--r-- | models/twofactor.go | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/models/twofactor.go b/models/twofactor.go index 36ff5db422..526ab917e8 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() |