package identity import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "encoding/pem" "fmt" "os" ) var ( // DefaultSigningCurve is the default elliptic curve used for signing. DefaultSigningCurve = elliptic.P384 ExportedPublicKeySize = 215 ) func LoadSigningKeyFromFile(filePath string) (*ecdsa.PrivateKey, error) { masterKeyFile, err := os.ReadFile(filePath) if err != nil { return nil, err } // The second argument is not an error. derEncoded, _ := pem.Decode(masterKeyFile) if derEncoded == nil { return nil, fmt.Errorf("failed to decode master key file") } masterKey, err := x509.ParseECPrivateKey(derEncoded.Bytes) if err != nil { return nil, err } return masterKey, nil } // Generate generates a new ECDSA private key for signing. func Generate() (*ecdsa.PrivateKey, error) { return ecdsa.GenerateKey(DefaultSigningCurve(), rand.Reader) } // Sign signs the data with the private key. func Sign(priv *ecdsa.PrivateKey, data []byte) ([]byte, error) { return ecdsa.SignASN1(rand.Reader, priv, data) } // Verify verifies the signature of the data with the public key. func Verify(pub *ecdsa.PublicKey, data, signature []byte) bool { return ecdsa.VerifyASN1(pub, data, signature) } // ExportPrivateKey exports the private key as a byte slice. func ExportPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) { der, err := x509.MarshalECPrivateKey(key) if err != nil { return nil, err } return pem.EncodeToMemory(&pem.Block{ Type: "PRIVATE KEY", Bytes: der, }), nil } // ExportPublicKey exports the public key as a byte slice. func ExportPublicKey(key *ecdsa.PublicKey) ([]byte, error) { der, err := x509.MarshalPKIXPublicKey(key) if err != nil { return nil, err } return pem.EncodeToMemory(&pem.Block{ Type: "PUBLIC KEY", Bytes: der, }), nil } // ImportPrivateKey imports the private key from a byte slice. func ImportPrivateKey(keyBytes []byte) (*ecdsa.PrivateKey, error) { block, _ := pem.Decode(keyBytes) if block == nil { return nil, fmt.Errorf("failed to decode private key") } privKey, err := x509.ParseECPrivateKey(block.Bytes) if err != nil { return nil, err } return privKey, nil } // ImportPublicKey imports the public key from a byte slice. func ImportPublicKey(keyBytes []byte) (*ecdsa.PublicKey, error) { block, _ := pem.Decode(keyBytes) if block == nil { return nil, fmt.Errorf("failed to decode public key") } pubKeyAny, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil, err } pubKey, ok := pubKeyAny.(*ecdsa.PublicKey) if !ok { return nil, fmt.Errorf("not an ECDSA public key") } return pubKey, nil }