mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
# Which Problems Are Solved Currently ZITADEL only allows the use of RSA public keys for machine user authentication (jwt-bearer grant), including for system API users. Attempting to use ECDSA (e.g. P-256) or ED25519 keys results in `Errors.Internal` because `BytesToPublicKey` performs an `ifc.(*rsa.PublicKey)` type assertion that returns `(nil, nil)` for non-RSA keys, which then causes a nil key panic in go-jose during JWT verification. This is the same fix as #8433 (by @livio-a), rebased onto current `main`. # How the Problems Are Solved - `BytesToPublicKey` now returns `crypto.PublicKey` (the standard library interface) instead of `*rsa.PublicKey` - A type switch validates the parsed key is one of `*rsa.PublicKey`, `*ecdsa.PublicKey`, or `ed25519.PublicKey` - A new `ErrNoPublicKey` sentinel error is returned for unsupported key types instead of silently returning nil - Callers in `system_token.go` and `query/key.go` are updated to use the generic `crypto.PublicKey` interface # Additional Changes None # Additional Context Duplicate of #8433 which has been open since August 2024. We hit this bug while implementing OIDC bootstrap for an SGX enclave that generates ECDSA P-256 keys at runtime -- the `AddKey` API accepts the ECDSA SPKI PEM fine, but the subsequent `jwt-bearer` token exchange fails with `Errors.Internal` due to the nil key. --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Wim Van Laer <[email protected]>
117 lines
2.1 KiB
Go
117 lines
2.1 KiB
Go
package query
|
|
|
|
import (
|
|
"time"
|
|
|
|
zcrypto "github.com/zitadel/zitadel/internal/crypto"
|
|
"github.com/zitadel/zitadel/internal/query/projection"
|
|
)
|
|
|
|
type Key interface {
|
|
ID() string
|
|
Algorithm() string
|
|
Use() zcrypto.KeyUsage
|
|
Sequence() uint64
|
|
}
|
|
|
|
type PrivateKey interface {
|
|
Key
|
|
Expiry() time.Time
|
|
Key() *zcrypto.CryptoValue
|
|
}
|
|
|
|
type PublicKey interface {
|
|
Key
|
|
Expiry() time.Time
|
|
Key() interface{}
|
|
}
|
|
|
|
type PublicKeys struct {
|
|
SearchResponse
|
|
Keys []PublicKey
|
|
}
|
|
|
|
type key struct {
|
|
id string
|
|
creationDate time.Time
|
|
changeDate time.Time
|
|
sequence uint64
|
|
resourceOwner string
|
|
algorithm string
|
|
use zcrypto.KeyUsage
|
|
}
|
|
|
|
func (k *key) ID() string {
|
|
return k.id
|
|
}
|
|
|
|
func (k *key) Algorithm() string {
|
|
return k.algorithm
|
|
}
|
|
|
|
func (k *key) Use() zcrypto.KeyUsage {
|
|
return k.use
|
|
}
|
|
|
|
func (k *key) Sequence() uint64 {
|
|
return k.sequence
|
|
}
|
|
|
|
var (
|
|
keyTable = table{
|
|
name: projection.KeyProjectionTable,
|
|
instanceIDCol: projection.KeyColumnInstanceID,
|
|
}
|
|
KeyColID = Column{
|
|
name: projection.KeyColumnID,
|
|
table: keyTable,
|
|
}
|
|
KeyColCreationDate = Column{
|
|
name: projection.KeyColumnCreationDate,
|
|
table: keyTable,
|
|
}
|
|
KeyColChangeDate = Column{
|
|
name: projection.KeyColumnChangeDate,
|
|
table: keyTable,
|
|
}
|
|
KeyColResourceOwner = Column{
|
|
name: projection.KeyColumnResourceOwner,
|
|
table: keyTable,
|
|
}
|
|
KeyColInstanceID = Column{
|
|
name: projection.KeyColumnInstanceID,
|
|
table: keyTable,
|
|
}
|
|
KeyColSequence = Column{
|
|
name: projection.KeyColumnSequence,
|
|
table: keyTable,
|
|
}
|
|
KeyColAlgorithm = Column{
|
|
name: projection.KeyColumnAlgorithm,
|
|
table: keyTable,
|
|
}
|
|
KeyColUse = Column{
|
|
name: projection.KeyColumnUse,
|
|
table: keyTable,
|
|
}
|
|
)
|
|
|
|
var (
|
|
keyPrivateTable = table{
|
|
name: projection.KeyPrivateTable,
|
|
instanceIDCol: projection.KeyPrivateColumnInstanceID,
|
|
}
|
|
KeyPrivateColID = Column{
|
|
name: projection.KeyPrivateColumnID,
|
|
table: keyPrivateTable,
|
|
}
|
|
KeyPrivateColExpiry = Column{
|
|
name: projection.KeyPrivateColumnExpiry,
|
|
table: keyPrivateTable,
|
|
}
|
|
KeyPrivateColKey = Column{
|
|
name: projection.KeyPrivateColumnKey,
|
|
table: keyPrivateTable,
|
|
}
|
|
)
|