mirror of
https://github.com/distribution/distribution.git
synced 2025-04-27 11:11:33 +00:00
fix: implement JWK thumbprint for Ed25519 public keys
Signed-off-by: Youfu Zhang <zhangyoufu@gmail.com>
This commit is contained in:
parent
e016d9595f
commit
4aab88fede
@ -690,7 +690,7 @@ Default `signingalgorithms`:
|
||||
Additional notes on `rootcertbundle`:
|
||||
|
||||
- The public key of this certificate will be automatically added to the list of known keys.
|
||||
- The public key will be identified by it's [RFC7638 Thumbprint](https://datatracker.ietf.org/doc/html/rfc7638).
|
||||
- The public key will be identified by its JWK Thumbprint. See [RFC 7638](https://datatracker.ietf.org/doc/html/rfc7638) and [RFC 8037](https://datatracker.ietf.org/doc/html/rfc8037) for reference.
|
||||
|
||||
For more information about Token based authentication configuration, see the
|
||||
[specification](../spec/auth/token.md).
|
||||
|
@ -351,7 +351,7 @@ func newAccessController(options map[string]interface{}) (auth.AccessController,
|
||||
rootPool := x509.NewCertPool()
|
||||
for _, rootCert := range rootCerts {
|
||||
rootPool.AddCert(rootCert)
|
||||
if key := GetRFC7638Thumbprint(rootCert.PublicKey); key != "" {
|
||||
if key := GetJWKThumbprint(rootCert.PublicKey); key != "" {
|
||||
trustedKeys[key] = rootCert.PublicKey
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package token
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
@ -54,15 +55,26 @@ func hashAndEncode(payload string) string {
|
||||
return base64.RawURLEncoding.EncodeToString(shasum[:])
|
||||
}
|
||||
|
||||
// Deprecated: use GetJWKThumbprint instead.
|
||||
func GetRFC7638Thumbprint(publickey crypto.PublicKey) string {
|
||||
return getJWKThumbprint(publickey, true)
|
||||
}
|
||||
|
||||
// GetJWKThumbprint calculates the JWK thumbprint of a public key.
|
||||
// The current implementation uses SHA256, but this algorithm may change
|
||||
// in the future as cryptographic best practices evolve. It returns an
|
||||
// empty string if the public key type is not supported.
|
||||
func GetJWKThumbprint(publickey crypto.PublicKey) string {
|
||||
return getJWKThumbprint(publickey, false)
|
||||
}
|
||||
|
||||
// RFC7638 states in section 3 sub 1 that the keys in the JSON object payload
|
||||
// are required to be ordered lexicographical order. Golang does not guarantee
|
||||
// order of keys[0]
|
||||
// [0]: https://groups.google.com/g/golang-dev/c/zBQwhm3VfvU
|
||||
//
|
||||
// The payloads are small enough to create the JSON strings manually
|
||||
func GetRFC7638Thumbprint(publickey crypto.PublicKey) string {
|
||||
var payload string
|
||||
|
||||
func getJWKThumbprint(publickey crypto.PublicKey, skipED25519 bool) string {
|
||||
switch pubkey := publickey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
e_big := big.NewInt(int64(pubkey.E)).Bytes()
|
||||
@ -70,17 +82,22 @@ func GetRFC7638Thumbprint(publickey crypto.PublicKey) string {
|
||||
e := base64.RawURLEncoding.EncodeToString(e_big)
|
||||
n := base64.RawURLEncoding.EncodeToString(pubkey.N.Bytes())
|
||||
|
||||
payload = fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`, e, n)
|
||||
return hashAndEncode(fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`, e, n))
|
||||
case *ecdsa.PublicKey:
|
||||
params := pubkey.Params()
|
||||
crv := params.Name
|
||||
x := base64.RawURLEncoding.EncodeToString(params.Gx.Bytes())
|
||||
y := base64.RawURLEncoding.EncodeToString(params.Gy.Bytes())
|
||||
|
||||
payload = fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`, crv, x, y)
|
||||
return hashAndEncode(fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`, crv, x, y))
|
||||
case ed25519.PublicKey:
|
||||
if skipED25519 {
|
||||
return ""
|
||||
}
|
||||
x := base64.RawURLEncoding.EncodeToString(pubkey)
|
||||
|
||||
return hashAndEncode(fmt.Sprintf(`{"crv":"Ed25519","kty":"OTP","x":"%s"}`, x))
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
return hashAndEncode(payload)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user