-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhotp.go
40 lines (32 loc) · 1.05 KB
/
hotp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package totp
import (
"math"
"strings"
"crypto/hmac"
"encoding/binary"
"fmt"
)
// ValidateHOTP is a wrapper around the HOTP validation operations
func ValidateHOTP(expectedHOTP string, counter uint64, opts AuthOpts) (bool, error) {
generatedHOTP, err := GenerateHOTP(opts, counter)
if err != nil {
return false, err
}
return strings.Compare(expectedHOTP, generatedHOTP) == 0, nil
}
// GenerateHOTP function generates the HOTP based on the AuthOpts
func GenerateHOTP(opts AuthOpts, counter uint64) (string, error) {
algo, err := ReturnHash(opts.Algo)
if err != nil {
return "", err
}
buf := make([]byte, 20)
mac := hmac.New(algo, StringToBytes(opts.Secret))
binary.BigEndian.PutUint64(buf, counter)
mac.Write(buf)
sum := mac.Sum(nil)
offset := sum[len(sum)-1] & 0xf
value := int64(((int(sum[offset]) & 0x7f) << 24) | ((int(sum[offset+1] & 0xff)) << 16) | ((int(sum[offset+2] & 0xff)) << 8) | (int(sum[offset+3]) & 0xff))
mod := int32(value % int64(math.Pow10(opts.Digits)))
return fmt.Sprintf(fmt.Sprintf("%%0%dd", opts.Digits), mod), nil
}