1615e146b6
Co-authored-by: zero <108243503+0xzer@users.noreply.github.com>
139 lines
3.2 KiB
Go
139 lines
3.2 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/big"
|
|
)
|
|
|
|
type JWK struct {
|
|
Kty string `json:"kty"`
|
|
Crv string `json:"crv"`
|
|
D string `json:"d"`
|
|
X string `json:"x"`
|
|
Y string `json:"y"`
|
|
Ext bool `json:"ext"`
|
|
KeyOps []string `json:"key_ops"`
|
|
PrivateBytes []byte `json:"private_bytes,omitempty"`
|
|
}
|
|
|
|
func (t *JWK) GetPrivateKey() (*ecdsa.PrivateKey, error) {
|
|
curve := elliptic.P256()
|
|
xBytes, err := base64.RawURLEncoding.DecodeString(t.X)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
yBytes, err := base64.RawURLEncoding.DecodeString(t.Y)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
dBytes, err := base64.RawURLEncoding.DecodeString(t.D)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
priv := &ecdsa.PrivateKey{
|
|
PublicKey: ecdsa.PublicKey{
|
|
Curve: curve,
|
|
X: new(big.Int).SetBytes(xBytes),
|
|
Y: new(big.Int).SetBytes(yBytes),
|
|
},
|
|
D: new(big.Int).SetBytes(dBytes),
|
|
}
|
|
return priv, nil
|
|
}
|
|
|
|
// Returns a byte slice containing the JWK and an error if the generation or export failed.
|
|
func (t *JWK) Marshal() ([]byte, error) {
|
|
JWKJSON, err := json.Marshal(t)
|
|
if err != nil {
|
|
fmt.Printf("Failed to marshal JWK: %v", err)
|
|
return nil, err
|
|
}
|
|
fmt.Printf("%s\n", JWKJSON)
|
|
return JWKJSON, err
|
|
}
|
|
|
|
func (t *JWK) PrivKeyB64Bytes() ([]byte, error) {
|
|
decodedPrivateKey, err2 := base64.RawURLEncoding.DecodeString(t.D)
|
|
return decodedPrivateKey, err2
|
|
}
|
|
|
|
func (t *JWK) ExtractPublicKeyDetails(pubKey []byte) *JWK {
|
|
x := base64.RawURLEncoding.EncodeToString(pubKey[1:33])
|
|
y := base64.RawURLEncoding.EncodeToString(pubKey[33:])
|
|
return &JWK{
|
|
Kty: "EC",
|
|
Crv: "P-256",
|
|
X: x,
|
|
Y: y,
|
|
}
|
|
}
|
|
|
|
func (t *JWK) DecompressPubkey() (*ecdsa.PublicKey, error) {
|
|
xBytes, err := base64.RawURLEncoding.DecodeString(t.X)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
yBytes, err := base64.RawURLEncoding.DecodeString(t.Y)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
x := new(big.Int).SetBytes(xBytes)
|
|
y := new(big.Int).SetBytes(yBytes)
|
|
pubKey := &ecdsa.PublicKey{
|
|
Curve: elliptic.P256(),
|
|
X: x,
|
|
Y: y,
|
|
}
|
|
return pubKey, nil
|
|
}
|
|
|
|
func (t *JWK) UncompressPubKey() ([]byte, error) {
|
|
xBytes, err := base64.RawURLEncoding.DecodeString(t.X)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
yBytes, err := base64.RawURLEncoding.DecodeString(t.Y)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
x := new(big.Int).SetBytes(xBytes)
|
|
y := new(big.Int).SetBytes(yBytes)
|
|
|
|
pubKey := &ecdsa.PublicKey{
|
|
Curve: elliptic.P256(),
|
|
X: x,
|
|
Y: y,
|
|
}
|
|
|
|
uncompressedPubKey := elliptic.Marshal(pubKey.Curve, pubKey.X, pubKey.Y)
|
|
|
|
return uncompressedPubKey, nil
|
|
}
|
|
|
|
// GenerateECDSA_P256_JWK generates a new ECDSA private key with P-256 curve
|
|
func GenerateECDSA_P256_JWK() (*JWK, error) {
|
|
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
if err != nil {
|
|
fmt.Printf("Failed to generate private key: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
JWK := &JWK{
|
|
Kty: "EC",
|
|
Crv: "P-256",
|
|
D: base64.RawURLEncoding.EncodeToString(privKey.D.Bytes()),
|
|
X: base64.RawURLEncoding.EncodeToString(privKey.X.Bytes()),
|
|
Y: base64.RawURLEncoding.EncodeToString(privKey.Y.Bytes()),
|
|
Ext: true,
|
|
KeyOps: []string{"sign"},
|
|
}
|
|
return JWK, nil
|
|
}
|