Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): Requires unique kids #1905

Merged
merged 3 commits into from
Feb 5, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 35 additions & 42 deletions service/internal/security/standard_crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,11 @@
type keylist map[string]any

type StandardCrypto struct {
// Lists of keys first sorted by algorithm
keys map[string]keylist
// Lists of keysByAlg first sorted by algorithm
keysByAlg map[string]keylist

// Lists all keys by identifier.
keysByID keylist
}

// NewStandardCrypto Create a new instance of standard crypto
Expand All @@ -83,20 +86,26 @@
}

func loadKeys(ks []KeyPairInfo) (*StandardCrypto, error) {
keys := make(map[string]keylist)
keysByAlg := make(map[string]keylist)
keysByID := make(keylist)
for _, k := range ks {
slog.Info("crypto cfg loading", "id", k.KID, "alg", k.Algorithm)
if _, ok := keys[k.Algorithm]; !ok {
keys[k.Algorithm] = make(map[string]any)
if _, ok := keysByID[k.KID]; ok {
return nil, fmt.Errorf("duplicate key identifier [%s]", k.KID)
}
if _, ok := keysByAlg[k.Algorithm]; !ok {
keysByAlg[k.Algorithm] = make(map[string]any)
}
loadedKey, err := loadKey(k)
if err != nil {
return nil, err
}
keys[k.Algorithm][k.KID] = loadedKey
keysByAlg[k.Algorithm][k.KID] = loadedKey
keysByID[k.KID] = loadedKey
}
return &StandardCrypto{
keys: keys,
keysByAlg: keysByAlg,
keysByID: keysByID,
}, nil
}

Expand Down Expand Up @@ -139,13 +148,14 @@
}

func loadDeprecatedKeys(rsaKeys map[string]StandardKeyInfo, ecKeys map[string]StandardKeyInfo) (*StandardCrypto, error) {
keys := make(map[string]keylist)
keysByAlg := make(map[string]keylist)
keysByID := make(keylist)

if len(ecKeys) > 0 {
keys[AlgorithmECP256R1] = make(map[string]any)
keysByAlg[AlgorithmECP256R1] = make(map[string]any)
}
if len(rsaKeys) > 0 {
keys[AlgorithmRSA2048] = make(map[string]any)
keysByAlg[AlgorithmRSA2048] = make(map[string]any)
}

for id, kasInfo := range rsaKeys {
Expand All @@ -169,7 +179,7 @@
return nil, fmt.Errorf("ocrypto.NewAsymEncryption failed: %w", err)
}

keys[AlgorithmRSA2048][id] = StandardRSACrypto{
k := StandardRSACrypto{
KeyPairInfo: KeyPairInfo{
Algorithm: AlgorithmRSA2048,
KID: id,
Expand All @@ -179,6 +189,8 @@
asymDecryption: asymDecryption,
asymEncryption: asymEncryption,
}
keysByAlg[AlgorithmRSA2048][id] = k
keysByID[id] = k
}
for id, kasInfo := range ecKeys {
slog.Info("cfg.ECKeys", "id", id, "kasInfo", kasInfo)
Expand All @@ -192,7 +204,7 @@
if err != nil {
return nil, fmt.Errorf("failed to EC certificate file: %w", err)
}
keys[AlgorithmECP256R1][id] = StandardECCrypto{
k := StandardECCrypto{
KeyPairInfo: KeyPairInfo{
Algorithm: AlgorithmRSA2048,
KID: id,
Expand All @@ -202,15 +214,17 @@
ecPrivateKeyPem: string(privatePemData),
ecCertificatePEM: string(ecCertificatePEM),
}
keysByAlg[AlgorithmECP256R1][id] = k
keysByID[id] = k
}

return &StandardCrypto{
keys: keys,
keysByAlg: keysByAlg,
}, nil
}

func (s StandardCrypto) FindKID(alg string) string {
if ks, ok := s.keys[alg]; ok && len(ks) > 0 {
if ks, ok := s.keysByAlg[alg]; ok && len(ks) > 0 {
for kid := range ks {
return kid
}
Expand All @@ -219,11 +233,7 @@
}

func (s StandardCrypto) RSAPublicKey(kid string) (string, error) {
rsaKeys, ok := s.keys[AlgorithmRSA2048]
if !ok || len(rsaKeys) == 0 {
return "", ErrCertNotFound
}
k, ok := rsaKeys[kid]
k, ok := s.keysByID[kid]
if !ok {
return "", ErrCertNotFound
}
Expand All @@ -240,12 +250,8 @@
return pem, nil
}

func (s StandardCrypto) ECCertificate(kid string) (string, error) {

Check failure on line 253 in service/internal/security/standard_crypto.go

View workflow job for this annotation

GitHub Actions / go (service)

unused-parameter: parameter 'kid' seems to be unused, consider removing or renaming it as _ (revive)
ecKeys, ok := s.keys[AlgorithmECP256R1]
if !ok || len(ecKeys) == 0 {
return "", ErrCertNotFound
}
k, ok := ecKeys[kid]
k, ok := s.keysByID[AlgorithmECP256R1]
jentfoo marked this conversation as resolved.
Show resolved Hide resolved
if !ok {
return "", ErrCertNotFound
}
Expand All @@ -257,11 +263,7 @@
}

func (s StandardCrypto) ECPublicKey(kid string) (string, error) {
ecKeys, ok := s.keys[AlgorithmECP256R1]
if !ok || len(ecKeys) == 0 {
return "", ErrCertNotFound
}
k, ok := ecKeys[kid]
k, ok := s.keysByID[AlgorithmECP256R1]
jentfoo marked this conversation as resolved.
Show resolved Hide resolved
if !ok {
return "", ErrCertNotFound
}
Expand Down Expand Up @@ -293,11 +295,7 @@
}

func (s StandardCrypto) RSADecrypt(_ crypto.Hash, kid string, _ string, ciphertext []byte) ([]byte, error) {
rsaKeys, ok := s.keys[AlgorithmRSA2048]
if !ok || len(rsaKeys) == 0 {
return nil, ErrCertNotFound
}
k, ok := rsaKeys[kid]
k, ok := s.keysByID[kid]
if !ok {
return nil, ErrCertNotFound
}
Expand All @@ -315,11 +313,10 @@
}

func (s StandardCrypto) RSAPublicKeyAsJSON(kid string) (string, error) {
rsaKeys, ok := s.keys[AlgorithmRSA2048]
if !ok || len(rsaKeys) == 0 {
k, ok := s.keysByID[kid]
if !ok {
return "", ErrCertNotFound
}
k, ok := rsaKeys[kid]
if !ok {
return "", ErrCertNotFound
}
Expand Down Expand Up @@ -357,11 +354,7 @@
}
ephemeralECDSAPublicKeyPEM := pem.EncodeToMemory(pemBlock)

ecKeys, ok := s.keys[AlgorithmECP256R1]
if !ok || len(ecKeys) == 0 {
return nil, ErrNoKeys
}
k, ok := ecKeys[kasKID]
k, ok := s.keysByID[kasKID]
if !ok {
return nil, ErrKeyPairInfoNotFound
}
Expand Down
Loading