]> source.dussan.org Git - gitea.git/commitdiff
go back to using CFB for AES decryption/encryption for 2FA (#3274)
authorMorgan Bazalgette <git@howl.moe>
Sun, 31 Dec 2017 02:19:42 +0000 (03:19 +0100)
committerLauris BH <lauris@nix.lv>
Sun, 31 Dec 2017 02:19:42 +0000 (04:19 +0200)
models/twofactor.go

index 36ff5db422c66d7f0cbc44fb1fca5b5bb5e7223d..526ab917e8f9fcd5a4a2b6c2d43b992f292f0674 100644 (file)
@@ -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()