133 lines
2.7 KiB
Go
133 lines
2.7 KiB
Go
package encrypt
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"github.com/emmansun/gmsm/sm2"
|
|
"github.com/emmansun/gmsm/smx509"
|
|
)
|
|
|
|
type KeyType string
|
|
|
|
const (
|
|
Raw KeyType = "raw"
|
|
Hex = "hex"
|
|
Base64 = "base64"
|
|
Pem = "pem"
|
|
)
|
|
|
|
const publicPemFormat = `-----BEGIN PUBLIC KEY-----
|
|
%s
|
|
-----END PUBLIC KEY-----`
|
|
|
|
const privatePemFormat = `-----BEGIN PRIVATE KEY-----
|
|
%s
|
|
-----END PRIVATE KEY-----`
|
|
|
|
func ParsePublicKey(key string, kt KeyType) (*ecdsa.PublicKey, error) {
|
|
if len(key) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
switch kt {
|
|
case Raw:
|
|
return sm2.NewPublicKey([]byte(key))
|
|
case Hex:
|
|
pubBytes, err := hex.DecodeString(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return sm2.NewPublicKey(pubBytes)
|
|
case Base64:
|
|
pubBytes, err := base64.StdEncoding.DecodeString(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return sm2.NewPublicKey(pubBytes)
|
|
case Pem:
|
|
pubPEM := fmt.Sprintf(publicPemFormat, key)
|
|
block, _ := pem.Decode([]byte(pubPEM))
|
|
if block == nil {
|
|
return nil, fmt.Errorf("failed to parse PEM block containing the public key")
|
|
}
|
|
|
|
pub, err := smx509.ParsePKIXPublicKey(block.Bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !sm2.IsSM2PublicKey(pub) {
|
|
return nil, fmt.Errorf("not a SM2 public key")
|
|
}
|
|
|
|
if key, ok := pub.(*ecdsa.PublicKey); ok {
|
|
return key, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("not a valid SM2 public key")
|
|
default:
|
|
return nil, nil
|
|
}
|
|
}
|
|
|
|
func ParsePrivateKey(key string, kt KeyType) (*sm2.PrivateKey, error) {
|
|
if len(key) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
switch kt {
|
|
case Raw:
|
|
return sm2.NewPrivateKey([]byte(key))
|
|
case Hex:
|
|
priBytes, err := hex.DecodeString(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return sm2.NewPrivateKey(priBytes)
|
|
case Base64:
|
|
priBytes, err := base64.StdEncoding.DecodeString(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return sm2.NewPrivateKey(priBytes)
|
|
case Pem:
|
|
priPEM := fmt.Sprintf(privatePemFormat, key)
|
|
block, _ := pem.Decode([]byte(priPEM))
|
|
if block == nil {
|
|
return nil, fmt.Errorf("failed to parse PEM block containing the private key")
|
|
}
|
|
|
|
pri, err := smx509.ParsePKCS8PrivateKey(block.Bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if pk, ok := pri.(*sm2.PrivateKey); ok {
|
|
return pk, nil
|
|
}
|
|
return nil, fmt.Errorf("not a valid SM2 private key")
|
|
default:
|
|
return nil, fmt.Errorf("unsupported key type")
|
|
}
|
|
}
|
|
|
|
func PriToPub(priKey string) (string, error) {
|
|
priBytes, err := hex.DecodeString(priKey)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
priObj, err := sm2.NewPrivateKey(priBytes)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
pubBytes, err := smx509.MarshalPKIXPublicKey(&priObj.PublicKey)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return hex.EncodeToString(pubBytes), nil
|
|
}
|