| 1 |
|
package web |
| 2 |
|
|
| 3 |
|
import ( |
| 4 |
|
"fmt" |
| 5 |
|
|
| 6 |
|
"github.com/dolthub/dolt/go/libraries/doltcore/creds" |
| 7 |
|
) |
| 8 |
|
|
| 9 |
|
// ed25519PubKeyLen is the raw length of an Ed25519 public key. dolt encodes it |
| 10 |
|
// as 52 base32 characters (creds.B32EncodedPubKeyLen) in its custom alphabet. |
| 11 |
|
const ed25519PubKeyLen = 32 |
| 12 |
|
|
| 13 |
|
// decodeDoltPubKey decodes the base32 public-key string that the dolt CLI emits. |
| 14 |
|
// It is exactly the string `dolt login` appends to the login URL as a fragment |
| 15 |
|
// (creds.DoltCreds.PubKeyBase32Str: creds.B32CredsEncoding over the raw 32-byte |
| 16 |
|
// key, custom alphabet "0123456789abcdefghijklmnopqrstuv", no padding). It |
| 17 |
|
// returns the raw 32-byte key and its derived key id (kid = |
| 18 |
|
// base32(SHA-512/224(pubkey)) via creds.PubKeyToKIDStr), matching exactly what |
| 19 |
|
// the Bearer-JWT verifier in authn expects to look up. |
| 20 |
|
// |
| 21 |
|
// It validates the decoded length is exactly 32 bytes; a wrong length is a |
| 22 |
|
// malformed key and is rejected loudly rather than stored. |
| 23 |
2 |
func decodeDoltPubKey(s string) (pubkey []byte, kid string, err error) { |
| 24 |
2 |
if s == "" { |
| 25 |
0 |
return nil, "", fmt.Errorf("empty public key") |
| 26 |
0 |
} |
| 27 |
2 |
pubkey, err = creds.B32CredsEncoding.DecodeString(s) |
| 28 |
2 |
if err != nil { |
| 29 |
1 |
return nil, "", fmt.Errorf("invalid base32 public key: %w", err) |
| 30 |
1 |
} |
| 31 |
1 |
if len(pubkey) != ed25519PubKeyLen { |
| 32 |
0 |
return nil, "", fmt.Errorf("public key must be %d bytes, got %d", ed25519PubKeyLen, len(pubkey)) |
| 33 |
0 |
} |
| 34 |
1 |
kid = creds.PubKeyToKIDStr(pubkey) |
| 35 |
1 |
return pubkey, kid, nil |
| 36 |
|
} |