gmessages/libgm/crypto/ecdsa.go
2023-07-16 14:36:13 +03:00

67 lines
1.6 KiB
Go

package crypto
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/base64"
"fmt"
"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
}
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")
}
*rub = make([]byte, base64.RawURLEncoding.DecodedLen(len(in)-2))
_, err := base64.RawURLEncoding.Decode(*rub, in[1:len(in)-1])
return err
}
type JWK struct {
KeyType string `json:"kty"`
Curve string `json:"crv"`
D RawURLBytes `json:"d"`
X RawURLBytes `json:"x"`
Y RawURLBytes `json:"y"`
}
func (t *JWK) GetPrivateKey() *ecdsa.PrivateKey {
return &ecdsa.PrivateKey{
PublicKey: *t.GetPublicKey(),
D: new(big.Int).SetBytes(t.D),
}
}
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),
}
}
// GenerateECDSAKey generates a new ECDSA private key with P-256 curve
func GenerateECDSAKey() *JWK {
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
panic(fmt.Errorf("failed to generate ecdsa key: %w", err))
}
return &JWK{
KeyType: "EC",
Curve: "P-256",
D: privKey.D.Bytes(),
X: privKey.X.Bytes(),
Y: privKey.Y.Bytes(),
}
}