refactor: split into subpackages and add AEAD/options/stream APIs with comprehensive tests

This commit is contained in:
2026-03-14 15:39:21 +08:00
parent e722b958a4
commit e89350b56a
54 changed files with 6040 additions and 1961 deletions
+138
View File
@@ -0,0 +1,138 @@
package asymm
import (
"bytes"
"testing"
)
func TestSM2SignVerifyAndEncryptDecrypt(t *testing.T) {
priv, pub, err := GenerateSM2Key()
if err != nil {
t.Fatalf("GenerateSM2Key failed: %v", err)
}
msg := []byte("sm2-message")
uid := []byte("user123")
sig, err := SM2Sign(priv, msg, uid)
if err != nil {
t.Fatalf("SM2Sign failed: %v", err)
}
if !SM2Verify(pub, msg, sig, uid) {
t.Fatalf("SM2Verify failed")
}
cipher, err := SM2EncryptASN1(pub, msg)
if err != nil {
t.Fatalf("SM2EncryptASN1 failed: %v", err)
}
plain, err := SM2DecryptASN1(priv, cipher)
if err != nil {
t.Fatalf("SM2DecryptASN1 failed: %v", err)
}
if !bytes.Equal(plain, msg) {
t.Fatalf("SM2 decrypt mismatch")
}
}
func TestSM2PEMEncodeDecode(t *testing.T) {
priv, pub, err := GenerateSM2Key()
if err != nil {
t.Fatalf("GenerateSM2Key failed: %v", err)
}
privPEM, err := EncodeSM2PrivateKey(priv, "pwd")
if err != nil {
t.Fatalf("EncodeSM2PrivateKey failed: %v", err)
}
pubPEM, err := EncodeSM2PublicKey(pub)
if err != nil {
t.Fatalf("EncodeSM2PublicKey failed: %v", err)
}
decodedPriv, err := DecodeSM2PrivateKey(privPEM, "pwd")
if err != nil {
t.Fatalf("DecodeSM2PrivateKey failed: %v", err)
}
decodedPub, err := DecodeSM2PublicKey(pubPEM)
if err != nil {
t.Fatalf("DecodeSM2PublicKey failed: %v", err)
}
msg := []byte("sm2-pem")
sig, err := SM2Sign(decodedPriv, msg, nil)
if err != nil {
t.Fatalf("SM2Sign failed: %v", err)
}
if !SM2Verify(decodedPub, msg, sig, nil) {
t.Fatalf("SM2 verify with decoded keys failed")
}
}
func TestSM9SignVerifyAndEncryptDecrypt(t *testing.T) {
signMasterPriv, signMasterPub, err := GenerateSM9SignMasterKey()
if err != nil {
t.Fatalf("GenerateSM9SignMasterKey failed: %v", err)
}
encryptMasterPriv, encryptMasterPub, err := GenerateSM9EncryptMasterKey()
if err != nil {
t.Fatalf("GenerateSM9EncryptMasterKey failed: %v", err)
}
uid := []byte("alice@example.com")
signUserKey, err := GenerateSM9SignUserKey(signMasterPriv, uid, 0)
if err != nil {
t.Fatalf("GenerateSM9SignUserKey failed: %v", err)
}
encryptUserKey, err := GenerateSM9EncryptUserKey(encryptMasterPriv, uid, 0)
if err != nil {
t.Fatalf("GenerateSM9EncryptUserKey failed: %v", err)
}
msg := []byte("sm9-message")
sig, err := SM9SignASN1(signUserKey, msg)
if err != nil {
t.Fatalf("SM9SignASN1 failed: %v", err)
}
if !SM9VerifyASN1(signMasterPub, uid, 0, msg, sig) {
t.Fatalf("SM9VerifyASN1 failed")
}
cipher, err := SM9Encrypt(encryptMasterPub, uid, 0, msg)
if err != nil {
t.Fatalf("SM9Encrypt failed: %v", err)
}
plain, err := SM9Decrypt(encryptUserKey, uid, cipher)
if err != nil {
t.Fatalf("SM9Decrypt failed: %v", err)
}
if !bytes.Equal(plain, msg) {
t.Fatalf("SM9 decrypt mismatch")
}
}
func TestSM9PEMEncodeDecode(t *testing.T) {
signMasterPriv, _, err := GenerateSM9SignMasterKey()
if err != nil {
t.Fatalf("GenerateSM9SignMasterKey failed: %v", err)
}
encryptMasterPriv, _, err := GenerateSM9EncryptMasterKey()
if err != nil {
t.Fatalf("GenerateSM9EncryptMasterKey failed: %v", err)
}
signPrivPEM, err := EncodeSM9SignMasterPrivateKey(signMasterPriv)
if err != nil {
t.Fatalf("EncodeSM9SignMasterPrivateKey failed: %v", err)
}
encPrivPEM, err := EncodeSM9EncryptMasterPrivateKey(encryptMasterPriv)
if err != nil {
t.Fatalf("EncodeSM9EncryptMasterPrivateKey failed: %v", err)
}
if _, err := DecodeSM9SignMasterPrivateKey(signPrivPEM); err != nil {
t.Fatalf("DecodeSM9SignMasterPrivateKey failed: %v", err)
}
if _, err := DecodeSM9EncryptMasterPrivateKey(encPrivPEM); err != nil {
t.Fatalf("DecodeSM9EncryptMasterPrivateKey failed: %v", err)
}
}
+113
View File
@@ -0,0 +1,113 @@
package asymm
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/pem"
"errors"
"golang.org/x/crypto/ssh"
)
func GenerateEcdsaKey(pubkeyCurve elliptic.Curve) (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) {
priv, err := ecdsa.GenerateKey(pubkeyCurve, rand.Reader)
if err != nil {
return nil, nil, err
}
return priv, &priv.PublicKey, nil
}
func EncodeEcdsaPrivateKey(private *ecdsa.PrivateKey, secret string) ([]byte, error) {
b, err := x509.MarshalECPrivateKey(private)
if err != nil {
return nil, err
}
if secret == "" {
return pem.EncodeToMemory(&pem.Block{
Type: "EC PRIVATE KEY",
Bytes: b,
}), nil
}
blk, err := x509.EncryptPEMBlock(rand.Reader, "EC PRIVATE KEY", b, []byte(secret), x509.PEMCipherAES256)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(blk), nil
}
func EncodeEcdsaPublicKey(public *ecdsa.PublicKey) ([]byte, error) {
publicBytes, err := x509.MarshalPKIXPublicKey(public)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicBytes,
}), nil
}
func DecodeEcdsaPrivateKey(private []byte, password string) (*ecdsa.PrivateKey, error) {
blk, _ := pem.Decode(private)
if blk == nil {
return nil, errors.New("private key error")
}
bytes, err := decodePEMBlockBytes(blk, password)
if err != nil {
return nil, err
}
if key, err := x509.ParseECPrivateKey(bytes); err == nil {
return key, nil
}
pkcs8, err := x509.ParsePKCS8PrivateKey(bytes)
if err != nil {
return nil, err
}
key, ok := pkcs8.(*ecdsa.PrivateKey)
if !ok {
return nil, errors.New("private key is not ECDSA")
}
return key, nil
}
func DecodeEcdsaPublicKey(pubStr []byte) (*ecdsa.PublicKey, error) {
blk, _ := pem.Decode(pubStr)
if blk == nil {
return nil, errors.New("public key error")
}
pub, err := x509.ParsePKIXPublicKey(blk.Bytes)
if err != nil {
return nil, err
}
key, ok := pub.(*ecdsa.PublicKey)
if !ok {
return nil, errors.New("public key is not ECDSA")
}
return key, nil
}
func EncodeEcdsaSSHPublicKey(public *ecdsa.PublicKey) ([]byte, error) {
publicKey, err := ssh.NewPublicKey(public)
if err != nil {
return nil, err
}
return ssh.MarshalAuthorizedKey(publicKey), nil
}
func GenerateEcdsaSSHKeyPair(pubkeyCurve elliptic.Curve, secret string) (string, string, error) {
pkey, pubkey, err := GenerateEcdsaKey(pubkeyCurve)
if err != nil {
return "", "", err
}
pub, err := EncodeEcdsaSSHPublicKey(pubkey)
if err != nil {
return "", "", err
}
priv, err := EncodeEcdsaPrivateKey(pkey, secret)
if err != nil {
return "", "", err
}
return string(priv), string(pub), nil
}
+161
View File
@@ -0,0 +1,161 @@
package asymm
import (
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"github.com/emmansun/gmsm/sm2"
"github.com/emmansun/gmsm/smx509"
"golang.org/x/crypto/ssh"
)
func EncodePrivateKey(private crypto.PrivateKey, secret string) ([]byte, error) {
switch key := private.(type) {
case *rsa.PrivateKey:
return EncodeRsaPrivateKey(key, secret)
case *ecdsa.PrivateKey:
return EncodeEcdsaPrivateKey(key, secret)
case *sm2.PrivateKey:
return EncodeSM2PrivateKey(key, secret)
default:
b, err := x509.MarshalPKCS8PrivateKey(private)
if err != nil {
return nil, err
}
if secret == "" {
return pem.EncodeToMemory(&pem.Block{
Type: "PRIVATE KEY",
Bytes: b,
}), nil
}
blk, err := x509.EncryptPEMBlock(rand.Reader, "PRIVATE KEY", b, []byte(secret), x509.PEMCipherAES256)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(blk), nil
}
}
func EncodePublicKey(public crypto.PublicKey) ([]byte, error) {
switch key := public.(type) {
case *rsa.PublicKey:
return EncodeRsaPublicKey(key)
case *ecdsa.PublicKey:
if sm2.IsSM2PublicKey(key) {
return EncodeSM2PublicKey(key)
}
return EncodeEcdsaPublicKey(key)
default:
publicBytes, err := x509.MarshalPKIXPublicKey(public)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicBytes,
}), nil
}
}
func DecodePrivateKey(private []byte, password string) (crypto.PrivateKey, error) {
blk, _ := pem.Decode(private)
if blk == nil {
return nil, errors.New("private key error")
}
switch blk.Type {
case "RSA PRIVATE KEY":
return DecodeRsaPrivateKey(private, password)
case "EC PRIVATE KEY":
return DecodeEcdsaPrivateKey(private, password)
case "SM2 PRIVATE KEY":
return DecodeSM2PrivateKey(private, password)
case "PRIVATE KEY":
bytes, err := decodePEMBlockBytes(blk, password)
if err != nil {
return nil, err
}
key, err := x509.ParsePKCS8PrivateKey(bytes)
if err == nil {
return key, nil
}
return smx509.ParsePKCS8PrivateKey(bytes)
case "OPENSSH PRIVATE KEY":
if password == "" {
return ssh.ParseRawPrivateKey(private)
}
return ssh.ParseRawPrivateKeyWithPassphrase(private, []byte(password))
default:
return nil, errors.New("private key type error")
}
}
func EncodeOpenSSHPrivateKey(private crypto.PrivateKey, secret string) ([]byte, error) {
key := interface{}(private)
if k, ok := private.(*ed25519.PrivateKey); ok {
key = *k
}
var (
block *pem.Block
err error
)
if secret == "" {
block, err = ssh.MarshalPrivateKey(key, "")
} else {
block, err = ssh.MarshalPrivateKeyWithPassphrase(key, "", []byte(secret))
}
if err != nil {
return nil, err
}
return pem.EncodeToMemory(block), nil
}
func DecodePublicKey(pubStr []byte) (crypto.PublicKey, error) {
blk, _ := pem.Decode(pubStr)
if blk == nil {
return nil, errors.New("public key error")
}
key, err := x509.ParsePKIXPublicKey(blk.Bytes)
if err == nil {
return key, nil
}
return smx509.ParsePKIXPublicKey(blk.Bytes)
}
func EncodeSSHPublicKey(public crypto.PublicKey) ([]byte, error) {
publicKey, err := ssh.NewPublicKey(public)
if err != nil {
return nil, err
}
return ssh.MarshalAuthorizedKey(publicKey), nil
}
func DecodeSSHPublicKey(pubStr []byte) (crypto.PublicKey, error) {
return ssh.ParsePublicKey(pubStr)
}
func decodePEMBlockBytes(blk *pem.Block, password string) ([]byte, error) {
if password == "" {
if x509.IsEncryptedPEMBlock(blk) || smx509.IsEncryptedPEMBlock(blk) {
return nil, errors.New("private key is encrypted but password is empty")
}
return blk.Bytes, nil
}
if x509.IsEncryptedPEMBlock(blk) {
if b, err := x509.DecryptPEMBlock(blk, []byte(password)); err == nil {
return b, nil
}
}
if smx509.IsEncryptedPEMBlock(blk) {
return smx509.DecryptPEMBlock(blk, []byte(password))
}
return blk.Bytes, nil
}
+204
View File
@@ -0,0 +1,204 @@
package asymm
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"math/big"
"golang.org/x/crypto/ssh"
)
func GenerateRsaKey(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
private, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, nil, err
}
return private, &private.PublicKey, nil
}
func EncodeRsaPrivateKey(private *rsa.PrivateKey, secret string) ([]byte, error) {
der := x509.MarshalPKCS1PrivateKey(private)
if secret == "" {
return pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: der,
}), nil
}
blk, err := x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", der, []byte(secret), x509.PEMCipherAES256)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(blk), nil
}
func EncodeRsaPublicKey(public *rsa.PublicKey) ([]byte, error) {
publicBytes, err := x509.MarshalPKIXPublicKey(public)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicBytes,
}), nil
}
func DecodeRsaPrivateKey(private []byte, password string) (*rsa.PrivateKey, error) {
blk, _ := pem.Decode(private)
if blk == nil {
return nil, errors.New("private key error")
}
bytes, err := decodePEMBlockBytes(blk, password)
if err != nil {
return nil, err
}
if prikey, err := x509.ParsePKCS1PrivateKey(bytes); err == nil {
return prikey, nil
}
pkcs8, err := x509.ParsePKCS8PrivateKey(bytes)
if err != nil {
return nil, err
}
prikey, ok := pkcs8.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("private key is not RSA")
}
return prikey, nil
}
func DecodeRsaPublicKey(pubStr []byte) (*rsa.PublicKey, error) {
blk, _ := pem.Decode(pubStr)
if blk == nil {
return nil, errors.New("public key error")
}
pub, err := x509.ParsePKIXPublicKey(blk.Bytes)
if err != nil {
return nil, err
}
rsapub, ok := pub.(*rsa.PublicKey)
if !ok {
return nil, errors.New("public key is not RSA")
}
return rsapub, nil
}
func EncodeRsaSSHPublicKey(public *rsa.PublicKey) ([]byte, error) {
publicKey, err := ssh.NewPublicKey(public)
if err != nil {
return nil, err
}
return ssh.MarshalAuthorizedKey(publicKey), nil
}
func GenerateRsaSSHKeyPair(bits int, secret string) (string, string, error) {
pkey, pubkey, err := GenerateRsaKey(bits)
if err != nil {
return "", "", err
}
pub, err := EncodeRsaSSHPublicKey(pubkey)
if err != nil {
return "", "", err
}
priv, err := EncodeRsaPrivateKey(pkey, secret)
if err != nil {
return "", "", err
}
return string(priv), string(pub), nil
}
func RSAEncrypt(pub *rsa.PublicKey, data []byte) ([]byte, error) {
return rsa.EncryptPKCS1v15(rand.Reader, pub, data)
}
func RSADecrypt(prikey *rsa.PrivateKey, data []byte) ([]byte, error) {
return rsa.DecryptPKCS1v15(rand.Reader, prikey, data)
}
func RSASign(msg, priKey []byte, password string, hashType crypto.Hash) ([]byte, error) {
prikey, err := DecodeRsaPrivateKey(priKey, password)
if err != nil {
return nil, err
}
hashed, err := hashMessage(msg, hashType)
if err != nil {
return nil, err
}
return rsa.SignPKCS1v15(rand.Reader, prikey, hashType, hashed)
}
func RSAVerify(sig, msg, pubKey []byte, hashType crypto.Hash) error {
pubkey, err := DecodeRsaPublicKey(pubKey)
if err != nil {
return err
}
hashed, err := hashMessage(msg, hashType)
if err != nil {
return err
}
return rsa.VerifyPKCS1v15(pubkey, hashType, hashed, sig)
}
func RSAEncryptByPrivkey(priv *rsa.PrivateKey, data []byte) ([]byte, error) {
return rsa.SignPKCS1v15(nil, priv, crypto.Hash(0), data)
}
func RSADecryptByPubkey(pub *rsa.PublicKey, data []byte) ([]byte, error) {
c := new(big.Int).SetBytes(data)
m := new(big.Int).Exp(c, big.NewInt(int64(pub.E)), pub.N)
em := leftPad(m.Bytes(), (pub.N.BitLen()+7)/8)
return unLeftPad(em)
}
func hashMessage(msg []byte, hashType crypto.Hash) ([]byte, error) {
if hashType == 0 {
return msg, nil
}
if !hashType.Available() {
return nil, errors.New("hash function is not available")
}
h := hashType.New()
_, err := h.Write(msg)
if err != nil {
return nil, err
}
return h.Sum(nil), nil
}
func leftPad(input []byte, size int) []byte {
n := len(input)
if n > size {
n = size
}
out := make([]byte, size)
copy(out[len(out)-n:], input)
return out
}
func unLeftPad(input []byte) ([]byte, error) {
// PKCS#1 v1.5 block format: 0x00 || 0x01 || PS(0xff...) || 0x00 || M
if len(input) < 3 {
return nil, errors.New("invalid RSA block")
}
if input[0] != 0x00 || input[1] != 0x01 {
return nil, errors.New("invalid RSA block header")
}
i := 2
for i < len(input) && input[i] == 0xff {
i++
}
if i >= len(input) || input[i] != 0x00 {
return nil, errors.New("invalid RSA block padding")
}
i++
if i > len(input) {
return nil, errors.New("invalid RSA block payload")
}
out := make([]byte, len(input)-i)
copy(out, input[i:])
return out, nil
}
+136
View File
@@ -0,0 +1,136 @@
package asymm
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"encoding/pem"
"errors"
"github.com/emmansun/gmsm/sm2"
"github.com/emmansun/gmsm/smx509"
)
func GenerateSM2Key() (*sm2.PrivateKey, *ecdsa.PublicKey, error) {
priv, err := sm2.GenerateKey(rand.Reader)
if err != nil {
return nil, nil, err
}
return priv, &priv.PublicKey, nil
}
func EncodeSM2PrivateKey(private *sm2.PrivateKey, secret string) ([]byte, error) {
der, err := smx509.MarshalSM2PrivateKey(private)
if err != nil {
return nil, err
}
if secret == "" {
return pem.EncodeToMemory(&pem.Block{Type: "SM2 PRIVATE KEY", Bytes: der}), nil
}
blk, err := smx509.EncryptPEMBlock(rand.Reader, "SM2 PRIVATE KEY", der, []byte(secret), smx509.PEMCipherAES256)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(blk), nil
}
func EncodeSM2PublicKey(public *ecdsa.PublicKey) ([]byte, error) {
der, err := smx509.MarshalPKIXPublicKey(public)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: der}), nil
}
func DecodeSM2PrivateKey(private []byte, password string) (*sm2.PrivateKey, error) {
blk, _ := pem.Decode(private)
if blk == nil {
return nil, errors.New("private key error")
}
bytes := blk.Bytes
if smx509.IsEncryptedPEMBlock(blk) {
if password == "" {
return nil, errors.New("private key is encrypted but password is empty")
}
var err error
bytes, err = smx509.DecryptPEMBlock(blk, []byte(password))
if err != nil {
return nil, err
}
}
if key, err := smx509.ParseSM2PrivateKey(bytes); err == nil {
return key, nil
}
pkcs8, err := smx509.ParsePKCS8PrivateKey(bytes)
if err != nil {
return nil, err
}
key, ok := pkcs8.(*sm2.PrivateKey)
if !ok {
return nil, errors.New("private key is not SM2")
}
return key, nil
}
func DecodeSM2PublicKey(pubStr []byte) (*ecdsa.PublicKey, error) {
blk, _ := pem.Decode(pubStr)
if blk == nil {
return nil, errors.New("public key error")
}
pubAny, err := smx509.ParsePKIXPublicKey(blk.Bytes)
if err != nil {
return nil, err
}
pub, ok := pubAny.(*ecdsa.PublicKey)
if !ok {
return nil, errors.New("public key is not ECDSA/SM2")
}
if !sm2.IsSM2PublicKey(pub) {
return nil, errors.New("public key is not SM2")
}
return pub, nil
}
func SM2EncryptASN1(pub *ecdsa.PublicKey, data []byte) ([]byte, error) {
return sm2.EncryptASN1(rand.Reader, pub, data)
}
func SM2DecryptASN1(priv *sm2.PrivateKey, data []byte) ([]byte, error) {
return priv.Decrypt(nil, data, sm2.ASN1DecrypterOpts)
}
func SM2Sign(priv *sm2.PrivateKey, msg, uid []byte) ([]byte, error) {
if len(uid) == 0 {
uid = nil
}
return sm2.SignASN1(rand.Reader, priv, msg, sm2.NewSM2SignerOption(true, uid))
}
func SM2Verify(pub *ecdsa.PublicKey, msg, sig, uid []byte) bool {
if len(uid) == 0 {
uid = nil
}
return sm2.VerifyASN1WithSM2(pub, uid, msg, sig)
}
func SM2SignByPEM(msg, priKey []byte, password string, uid []byte) ([]byte, error) {
priv, err := DecodeSM2PrivateKey(priKey, password)
if err != nil {
return nil, err
}
return SM2Sign(priv, msg, uid)
}
func SM2VerifyByPEM(sig, msg, pubKey []byte, uid []byte) (bool, error) {
pub, err := DecodeSM2PublicKey(pubKey)
if err != nil {
return false, err
}
return SM2Verify(pub, msg, sig, uid), nil
}
func IsSM2PublicKey(public crypto.PublicKey) bool {
return sm2.IsSM2PublicKey(public)
}
+236
View File
@@ -0,0 +1,236 @@
package asymm
import (
"crypto/rand"
"encoding/pem"
"errors"
gmsm3 "github.com/emmansun/gmsm/sm3"
gmsm9 "github.com/emmansun/gmsm/sm9"
)
const (
SM9SignHID byte = 0x01
SM9EncryptHID byte = 0x03
)
func GenerateSM9SignMasterKey() (*gmsm9.SignMasterPrivateKey, *gmsm9.SignMasterPublicKey, error) {
priv, err := gmsm9.GenerateSignMasterKey(rand.Reader)
if err != nil {
return nil, nil, err
}
return priv, priv.PublicKey(), nil
}
func GenerateSM9EncryptMasterKey() (*gmsm9.EncryptMasterPrivateKey, *gmsm9.EncryptMasterPublicKey, error) {
priv, err := gmsm9.GenerateEncryptMasterKey(rand.Reader)
if err != nil {
return nil, nil, err
}
return priv, priv.PublicKey(), nil
}
func GenerateSM9SignUserKey(master *gmsm9.SignMasterPrivateKey, uid []byte, hid byte) (*gmsm9.SignPrivateKey, error) {
if master == nil {
return nil, errors.New("sm9 sign master key is nil")
}
if hid == 0 {
hid = SM9SignHID
}
return master.GenerateUserKey(uid, hid)
}
func GenerateSM9EncryptUserKey(master *gmsm9.EncryptMasterPrivateKey, uid []byte, hid byte) (*gmsm9.EncryptPrivateKey, error) {
if master == nil {
return nil, errors.New("sm9 encrypt master key is nil")
}
if hid == 0 {
hid = SM9EncryptHID
}
return master.GenerateUserKey(uid, hid)
}
func EncodeSM9SignMasterPrivateKey(key *gmsm9.SignMasterPrivateKey) ([]byte, error) {
if key == nil {
return nil, errors.New("sm9 sign master private key is nil")
}
der, err := key.MarshalASN1()
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: "SM9 SIGN MASTER PRIVATE KEY", Bytes: der}), nil
}
func DecodeSM9SignMasterPrivateKey(data []byte) (*gmsm9.SignMasterPrivateKey, error) {
der, err := pemOrDER(data)
if err != nil {
return nil, err
}
return gmsm9.UnmarshalSignMasterPrivateKeyASN1(der)
}
func EncodeSM9SignMasterPublicKey(key *gmsm9.SignMasterPublicKey) ([]byte, error) {
if key == nil {
return nil, errors.New("sm9 sign master public key is nil")
}
der, err := key.MarshalASN1()
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: "SM9 SIGN MASTER PUBLIC KEY", Bytes: der}), nil
}
func DecodeSM9SignMasterPublicKey(data []byte) (*gmsm9.SignMasterPublicKey, error) {
der, err := pemOrDER(data)
if err != nil {
return nil, err
}
return gmsm9.UnmarshalSignMasterPublicKeyASN1(der)
}
func EncodeSM9SignPrivateKey(key *gmsm9.SignPrivateKey) ([]byte, error) {
if key == nil {
return nil, errors.New("sm9 sign private key is nil")
}
der, err := key.MarshalASN1()
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: "SM9 SIGN PRIVATE KEY", Bytes: der}), nil
}
func DecodeSM9SignPrivateKey(data []byte) (*gmsm9.SignPrivateKey, error) {
der, err := pemOrDER(data)
if err != nil {
return nil, err
}
return gmsm9.UnmarshalSignPrivateKeyASN1(der)
}
func EncodeSM9EncryptMasterPrivateKey(key *gmsm9.EncryptMasterPrivateKey) ([]byte, error) {
if key == nil {
return nil, errors.New("sm9 encrypt master private key is nil")
}
der, err := key.MarshalASN1()
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: "SM9 ENCRYPT MASTER PRIVATE KEY", Bytes: der}), nil
}
func DecodeSM9EncryptMasterPrivateKey(data []byte) (*gmsm9.EncryptMasterPrivateKey, error) {
der, err := pemOrDER(data)
if err != nil {
return nil, err
}
return gmsm9.UnmarshalEncryptMasterPrivateKeyASN1(der)
}
func EncodeSM9EncryptMasterPublicKey(key *gmsm9.EncryptMasterPublicKey) ([]byte, error) {
if key == nil {
return nil, errors.New("sm9 encrypt master public key is nil")
}
der, err := key.MarshalASN1()
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: "SM9 ENCRYPT MASTER PUBLIC KEY", Bytes: der}), nil
}
func DecodeSM9EncryptMasterPublicKey(data []byte) (*gmsm9.EncryptMasterPublicKey, error) {
der, err := pemOrDER(data)
if err != nil {
return nil, err
}
return gmsm9.UnmarshalEncryptMasterPublicKeyASN1(der)
}
func EncodeSM9EncryptPrivateKey(key *gmsm9.EncryptPrivateKey) ([]byte, error) {
if key == nil {
return nil, errors.New("sm9 encrypt private key is nil")
}
der, err := key.MarshalASN1()
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: "SM9 ENCRYPT PRIVATE KEY", Bytes: der}), nil
}
func DecodeSM9EncryptPrivateKey(data []byte) (*gmsm9.EncryptPrivateKey, error) {
der, err := pemOrDER(data)
if err != nil {
return nil, err
}
return gmsm9.UnmarshalEncryptPrivateKeyASN1(der)
}
func SM9SignHashASN1(priv *gmsm9.SignPrivateKey, hash []byte) ([]byte, error) {
if priv == nil {
return nil, errors.New("sm9 sign private key is nil")
}
return gmsm9.SignASN1(rand.Reader, priv, hash)
}
func SM9SignASN1(priv *gmsm9.SignPrivateKey, message []byte) ([]byte, error) {
sum := gmsm3.Sum(message)
return SM9SignHashASN1(priv, sum[:])
}
func SM9VerifyHashASN1(pub *gmsm9.SignMasterPublicKey, uid []byte, hid byte, hash, sig []byte) bool {
if pub == nil {
return false
}
if hid == 0 {
hid = SM9SignHID
}
return gmsm9.VerifyASN1(pub, uid, hid, hash, sig)
}
func SM9VerifyASN1(pub *gmsm9.SignMasterPublicKey, uid []byte, hid byte, message, sig []byte) bool {
sum := gmsm3.Sum(message)
return SM9VerifyHashASN1(pub, uid, hid, sum[:], sig)
}
func SM9Encrypt(pub *gmsm9.EncryptMasterPublicKey, uid []byte, hid byte, plaintext []byte) ([]byte, error) {
if pub == nil {
return nil, errors.New("sm9 encrypt master public key is nil")
}
if hid == 0 {
hid = SM9EncryptHID
}
return gmsm9.Encrypt(rand.Reader, pub, uid, hid, plaintext, gmsm9.SM4CBCEncrypterOpts)
}
func SM9Decrypt(priv *gmsm9.EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error) {
if priv == nil {
return nil, errors.New("sm9 encrypt private key is nil")
}
return gmsm9.Decrypt(priv, uid, ciphertext, gmsm9.SM4CBCEncrypterOpts)
}
func SM9EncryptASN1(pub *gmsm9.EncryptMasterPublicKey, uid []byte, hid byte, plaintext []byte) ([]byte, error) {
if pub == nil {
return nil, errors.New("sm9 encrypt master public key is nil")
}
if hid == 0 {
hid = SM9EncryptHID
}
return gmsm9.EncryptASN1(rand.Reader, pub, uid, hid, plaintext, gmsm9.SM4CBCEncrypterOpts)
}
func SM9DecryptASN1(priv *gmsm9.EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error) {
if priv == nil {
return nil, errors.New("sm9 encrypt private key is nil")
}
return gmsm9.DecryptASN1(priv, uid, ciphertext)
}
func pemOrDER(data []byte) ([]byte, error) {
if len(data) == 0 {
return nil, errors.New("empty key data")
}
if blk, _ := pem.Decode(data); blk != nil {
return blk.Bytes, nil
}
return data, nil
}