newdrive/internal/adapters/authn/credentials.go
Elijah 715423ab8e
Some checks failed
CI / Backend (push) Failing after 1s
CI / Frontend (push) Successful in 13s
CI / Contracts and repository policy (push) Failing after 3s
CI / Container (push) Has been skipped
Implement owner setup and browser authentication sessions
2026-07-16 19:45:40 -07:00

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()
}