55 lines
1.2 KiB
Go
55 lines
1.2 KiB
Go
package sshkeys
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"math/big"
|
|
"time"
|
|
|
|
"github.com/gliderlabs/ssh"
|
|
)
|
|
|
|
// KeyOneOf checks if keys is one of the given set of keys.
|
|
func KeyOneOf(keys []ssh.PublicKey, key ssh.PublicKey) bool {
|
|
return len(KeyIndexes(keys, key)) > 0
|
|
}
|
|
|
|
// KeyIndexes returns a slice of ints that contain the indexes of the given key.
|
|
func KeyIndexes(keys []ssh.PublicKey, key ssh.PublicKey) []int {
|
|
indexes := make([]int, 0, len(keys))
|
|
for i, cey := range keys {
|
|
if ssh.KeysEqual(key, cey) {
|
|
indexes = append(indexes, i)
|
|
}
|
|
}
|
|
return indexes
|
|
}
|
|
|
|
const (
|
|
slowdownMinDelay = time.Second / 10
|
|
slowdownJitter = time.Second / 10
|
|
)
|
|
|
|
// slowdown invokes f immediatly, but introduces a random delay to prevent timing attacks.
|
|
// the delay is also introduced if f() panics.
|
|
func Slowdown[T any](f func() T) T {
|
|
start := time.Now()
|
|
defer func() {
|
|
// sleep the minimum remaining time
|
|
remain := time.Since(start) - slowdownMinDelay
|
|
if remain > 0 {
|
|
time.Sleep(remain)
|
|
}
|
|
|
|
// find a second random delay
|
|
delay, err := rand.Int(rand.Reader, big.NewInt(int64(slowdownJitter)))
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// and wait that long
|
|
time.Sleep(time.Duration(delay.Int64()))
|
|
}()
|
|
|
|
return f()
|
|
|
|
}
|