2023-06-30 09:54:08 +00:00
|
|
|
package crypto
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"crypto/elliptic"
|
|
|
|
"crypto/rand"
|
|
|
|
"encoding/base64"
|
2023-07-15 17:43:28 +00:00
|
|
|
"fmt"
|
2023-06-30 09:54:08 +00:00
|
|
|
"math/big"
|
|
|
|
)
|
|
|
|
|
2023-07-16 10:33:51 +00:00
|
|
|
type RawURLBytes []byte
|
2023-07-09 11:16:52 +00:00
|
|
|
|
2023-07-16 10:33:51 +00:00
|
|
|
func (rub RawURLBytes) MarshalJSON() ([]byte, error) {
|
|
|
|
out := make([]byte, 2+base64.RawURLEncoding.EncodedLen(len(rub)))
|
|
|
|
out[0] = '"'
|
|
|
|
base64.RawURLEncoding.Encode(out[1:], rub)
|
|
|
|
out[len(out)-1] = '"'
|
|
|
|
return out, nil
|
2023-06-30 09:54:08 +00:00
|
|
|
}
|
|
|
|
|
2023-07-16 10:33:51 +00:00
|
|
|
func (rub *RawURLBytes) UnmarshalJSON(in []byte) error {
|
|
|
|
if len(in) < 2 || in[0] != '"' || in[len(in)-1] != '"' {
|
|
|
|
return fmt.Errorf("invalid value for RawURLBytes: not a JSON string")
|
2023-06-30 09:54:08 +00:00
|
|
|
}
|
2023-07-16 10:33:51 +00:00
|
|
|
*rub = make([]byte, base64.RawURLEncoding.DecodedLen(len(in)-2))
|
|
|
|
_, err := base64.RawURLEncoding.Decode(*rub, in[1:len(in)-1])
|
|
|
|
return err
|
|
|
|
}
|
2023-06-30 09:54:08 +00:00
|
|
|
|
2023-07-16 10:33:51 +00:00
|
|
|
type JWK struct {
|
|
|
|
KeyType string `json:"kty"`
|
|
|
|
Curve string `json:"crv"`
|
|
|
|
D RawURLBytes `json:"d"`
|
|
|
|
X RawURLBytes `json:"x"`
|
|
|
|
Y RawURLBytes `json:"y"`
|
2023-06-30 09:54:08 +00:00
|
|
|
}
|
|
|
|
|
2023-07-16 10:33:51 +00:00
|
|
|
func (t *JWK) GetPrivateKey() *ecdsa.PrivateKey {
|
|
|
|
return &ecdsa.PrivateKey{
|
|
|
|
PublicKey: *t.GetPublicKey(),
|
|
|
|
D: new(big.Int).SetBytes(t.D),
|
2023-06-30 09:54:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-16 10:33:51 +00:00
|
|
|
func (t *JWK) GetPublicKey() *ecdsa.PublicKey {
|
|
|
|
return &ecdsa.PublicKey{
|
|
|
|
Curve: elliptic.P256(),
|
|
|
|
X: new(big.Int).SetBytes(t.X),
|
|
|
|
Y: new(big.Int).SetBytes(t.Y),
|
2023-07-15 17:43:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-15 13:45:50 +00:00
|
|
|
// GenerateECDSAKey generates a new ECDSA private key with P-256 curve
|
2023-07-16 11:36:13 +00:00
|
|
|
func GenerateECDSAKey() *JWK {
|
2023-06-30 09:54:08 +00:00
|
|
|
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
|
|
if err != nil {
|
2023-07-16 11:36:13 +00:00
|
|
|
panic(fmt.Errorf("failed to generate ecdsa key: %w", err))
|
2023-06-30 09:54:08 +00:00
|
|
|
}
|
2023-07-15 13:45:50 +00:00
|
|
|
return &JWK{
|
|
|
|
KeyType: "EC",
|
|
|
|
Curve: "P-256",
|
2023-07-16 10:33:51 +00:00
|
|
|
D: privKey.D.Bytes(),
|
|
|
|
X: privKey.X.Bytes(),
|
|
|
|
Y: privKey.Y.Bytes(),
|
2023-07-16 11:36:13 +00:00
|
|
|
}
|
2023-06-30 09:55:49 +00:00
|
|
|
}
|