-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathderive_rfc6287.go
46 lines (38 loc) · 1.17 KB
/
derive_rfc6287.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
41
42
43
44
45
46
package otp
// deriveRFC6287 is based on https://datatracker.ietf.org/doc/html/rfc6287
func deriveRFC6287(secret []byte, s Suite, input OCRAInput) (string, error) {
if err := s.Validate(); err != nil {
return "", err
}
cfg := s.Config()
if err := input.Validate(cfg); err != nil {
return "", err
}
msgBuf := rfc6287BufPool.Get().(*[]byte)
defer rfc6287BufPool.Put(msgBuf)
msg := (*msgBuf)[:0]
msg = append(msg, []byte(cfg.Raw)...)
msg = append(msg, separator)
if cfg.IncludeCounter {
msg = append(msg, padBytes(input.Counter, 8)...) // 8 bytes
}
if cfg.IncludeChallenge {
msg = append(msg, padBytes(input.Challenge, 128)...) // 128 bytes
}
if cfg.IncludePassword {
msg = append(msg, input.Password...) // exact length (20,32,64)
}
if cfg.IncludeSession {
// For demo, we do pad up to 128, but you can adapt for S064, S128, etc.
msg = append(msg, padBytes(input.SessionInfo, 128)...)
}
if cfg.IncludeTimestamp {
msg = append(msg, padBytes(input.Timestamp, 8)...) // 8 bytes
}
hp := &hmacPools[cfg.Hash]
mac := hp.new(secret)
mac.Write(msg)
sum := mac.Sum(nil)
otp := truncate(sum, mod10[cfg.Digits])
return formatDecimal(otp, cfg.Digits), nil
}