OTP routines
This commit is contained in:
57
crypto.go
Normal file
57
crypto.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/base32"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ComputeHmac256(message string, secret string) []byte {
|
||||
h := hmac.New(sha256.New, []byte(secret))
|
||||
h.Write([]byte(message))
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
func encodeSecret(secret []byte) string {
|
||||
return strings.TrimRight(base32.StdEncoding.EncodeToString(secret), "=")
|
||||
}
|
||||
|
||||
func GenericTotpCode(secret string, t time.Time, algo string, digits int, period int) (string, error) {
|
||||
var mac hash.Hash
|
||||
var format string
|
||||
|
||||
now := [8]byte{}
|
||||
|
||||
binary.BigEndian.PutUint64(now[:], uint64(math.Floor(float64(t.Unix())/float64(period))))
|
||||
binsecret, _ := base32.StdEncoding.DecodeString(secret)
|
||||
|
||||
switch algo {
|
||||
case "sha1":
|
||||
mac = hmac.New(sha1.New, binsecret)
|
||||
case "sha256":
|
||||
mac = hmac.New(sha256.New, binsecret)
|
||||
default:
|
||||
return "", errors.New("unsupported algorithm")
|
||||
}
|
||||
|
||||
switch digits {
|
||||
case 6:
|
||||
format = "%06d"
|
||||
case 8:
|
||||
format = "%08d"
|
||||
default:
|
||||
return "", errors.New("unsupported code size")
|
||||
}
|
||||
|
||||
mac.Write(now[:])
|
||||
sum := mac.Sum(nil)
|
||||
return fmt.Sprintf(format, (binary.BigEndian.Uint32(sum[sum[len(sum)-1]&0xf:])&0x7fffffff)%1000000), nil
|
||||
}
|
||||
Reference in New Issue
Block a user