71 lines
1.5 KiB
Go
71 lines
1.5 KiB
Go
// FILE: auth/auth.go
|
|
package auth
|
|
|
|
import (
|
|
"crypto/rsa"
|
|
"fmt"
|
|
)
|
|
|
|
// Authenticator provides password hashing and JWT operations
|
|
type Authenticator struct {
|
|
algorithm string
|
|
jwtSecret []byte // For HS256
|
|
privateKey *rsa.PrivateKey // For RS256
|
|
publicKey *rsa.PublicKey // For RS256
|
|
argonTime uint32
|
|
argonMemory uint32
|
|
argonThreads uint8
|
|
}
|
|
|
|
// NewAuthenticator creates a new authenticator with specified algorithm
|
|
func NewAuthenticator(key any, algorithm ...string) (*Authenticator, error) {
|
|
alg := "HS256"
|
|
if len(algorithm) > 0 && algorithm[0] != "" {
|
|
alg = algorithm[0]
|
|
}
|
|
|
|
auth := &Authenticator{
|
|
algorithm: alg,
|
|
argonTime: DefaultArgonTime,
|
|
argonMemory: DefaultArgonMemory,
|
|
argonThreads: DefaultArgonThreads,
|
|
}
|
|
|
|
switch alg {
|
|
case "HS256":
|
|
secret, ok := key.([]byte)
|
|
if !ok {
|
|
return nil, ErrInvalidKeyType
|
|
}
|
|
if len(secret) < 32 {
|
|
return nil, ErrSecretTooShort
|
|
}
|
|
auth.jwtSecret = secret
|
|
|
|
case "RS256":
|
|
switch k := key.(type) {
|
|
case *rsa.PrivateKey:
|
|
auth.privateKey = k
|
|
auth.publicKey = &k.PublicKey
|
|
case *rsa.PublicKey:
|
|
auth.publicKey = k
|
|
case []byte:
|
|
// Try parsing as PEM
|
|
if privKey, err := parseRSAPrivateKey(k); err == nil {
|
|
auth.privateKey = privKey
|
|
auth.publicKey = &privKey.PublicKey
|
|
} else if pubKey, err := parseRSAPublicKey(k); err == nil {
|
|
auth.publicKey = pubKey
|
|
} else {
|
|
return nil, fmt.Errorf("failed to parse RSA key: %w", err)
|
|
}
|
|
default:
|
|
return nil, ErrInvalidKeyType
|
|
}
|
|
|
|
default:
|
|
return nil, ErrInvalidAlgorithm
|
|
}
|
|
|
|
return auth, nil
|
|
} |