46 lines
1.4 KiB
Go
46 lines
1.4 KiB
Go
package authn
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"encoding/base32"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"drive.local/drivev2/internal/application"
|
|
)
|
|
|
|
type CredentialGenerator struct{}
|
|
|
|
func (CredentialGenerator) NewCredential() (application.GeneratedCredential, error) {
|
|
secret := make([]byte, 32)
|
|
if _, err := rand.Read(secret); err != nil {
|
|
return application.GeneratedCredential{}, fmt.Errorf("generate credential: %w", err)
|
|
}
|
|
plaintext := base64.RawURLEncoding.EncodeToString(secret)
|
|
digest := sha256.Sum256([]byte(plaintext))
|
|
return application.GeneratedCredential{Plaintext: plaintext, Digest: digest[:]}, nil
|
|
}
|
|
|
|
func (CredentialGenerator) NewRecoveryCodes(count int) ([]application.GeneratedCredential, error) {
|
|
codes := make([]application.GeneratedCredential, 0, count)
|
|
for range count {
|
|
raw := make([]byte, 12)
|
|
if _, err := rand.Read(raw); err != nil {
|
|
return nil, fmt.Errorf("generate recovery code: %w", err)
|
|
}
|
|
encoded := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(raw)
|
|
plaintext := strings.Join([]string{encoded[0:5], encoded[5:10], encoded[10:15], encoded[15:20]}, "-")
|
|
digest := sha256.Sum256([]byte(plaintext))
|
|
codes = append(codes, application.GeneratedCredential{Plaintext: plaintext, Digest: digest[:]})
|
|
}
|
|
return codes, nil
|
|
}
|
|
|
|
type SystemClock struct{}
|
|
|
|
func (SystemClock) Now() time.Time {
|
|
return time.Now()
|
|
}
|