mirror of
https://github.com/passbolt/go-passbolt.git
synced 2025-05-09 17:48:20 +00:00
add totp generator from:
https://github.com/yitsushi/totp-cli/blob/master/security/otp.go
This commit is contained in:
parent
f01926b1c5
commit
663f5f6b76
1 changed files with 60 additions and 0 deletions
60
helper/totp.go
Normal file
60
helper/totp.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/base32"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
mask1 = 0xf
|
||||
mask2 = 0x7f
|
||||
mask3 = 0xff
|
||||
timeSplitInSeconds = 30
|
||||
shift24 = 24
|
||||
shift16 = 16
|
||||
shift8 = 8
|
||||
codeLength = 6
|
||||
)
|
||||
|
||||
// GenerateOTPCode generates a 6 digit TOTP from the secret Token.
|
||||
func GenerateOTPCode(token string, when time.Time) (string, error) {
|
||||
timer := uint64(math.Floor(float64(when.Unix()) / float64(timeSplitInSeconds)))
|
||||
// Remove spaces, some providers are giving us in a readable format
|
||||
// so they add spaces in there. If it's not removed while pasting in,
|
||||
// remove it now.
|
||||
token = strings.Replace(token, " ", "", -1)
|
||||
|
||||
// It should be uppercase always
|
||||
token = strings.ToUpper(token)
|
||||
|
||||
secretBytes, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(token)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Decoding token string: %w", err)
|
||||
}
|
||||
|
||||
buf := make([]byte, 8)
|
||||
mac := hmac.New(sha1.New, secretBytes)
|
||||
|
||||
binary.BigEndian.PutUint64(buf, timer)
|
||||
_, _ = mac.Write(buf)
|
||||
sum := mac.Sum(nil)
|
||||
|
||||
// http://tools.ietf.org/html/rfc4226#section-5.4
|
||||
offset := sum[len(sum)-1] & mask1
|
||||
value := int64(((int(sum[offset]) & mask2) << shift24) |
|
||||
((int(sum[offset+1] & mask3)) << shift16) |
|
||||
((int(sum[offset+2] & mask3)) << shift8) |
|
||||
(int(sum[offset+3]) & mask3))
|
||||
|
||||
modulo := int32(value % int64(math.Pow10(codeLength)))
|
||||
|
||||
format := fmt.Sprintf("%%0%dd", codeLength)
|
||||
|
||||
return fmt.Sprintf(format, modulo), nil
|
||||
}
|
Loading…
Add table
Reference in a new issue