gmessages/libgm/crypto/ecdsa.go

68 lines
1.6 KiB
Go
Raw Permalink Normal View History

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"
)
type RawURLBytes []byte
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
}
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
}
*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
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
}
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
}
}
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",
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
}