refactor: split into subpackages and add AEAD/options/stream APIs with comprehensive tests
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user