185 lines
4.5 KiB
Go
185 lines
4.5 KiB
Go
|
|
package xcrypto
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"crypto"
|
|||
|
|
"crypto/rand"
|
|||
|
|
"crypto/rsa"
|
|||
|
|
"crypto/x509"
|
|||
|
|
"encoding/base64"
|
|||
|
|
"encoding/pem"
|
|||
|
|
"errors"
|
|||
|
|
"golang.org/x/crypto/pkcs12"
|
|||
|
|
"io/ioutil"
|
|||
|
|
"os"
|
|||
|
|
"strings"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
const (
|
|||
|
|
PRIVATE_PEM_BEGIN = "-----BEGIN RSA PRIVATE KEY-----\n"
|
|||
|
|
PRIVATE_PEM_END = "\n-----END RSA PRIVATE KEY-----"
|
|||
|
|
PUBLIC_PEM_BEGIN = "-----BEGIN PUBLIC KEY-----\n"
|
|||
|
|
PUBLIC_PEM_END = "\n-----END PUBLIC KEY-----"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
type PublicStruct struct {
|
|||
|
|
publicKey *rsa.PublicKey
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (p PublicStruct) Verify(sign, content string, hash crypto.Hash) error {
|
|||
|
|
return Verify(sign, content, p.publicKey, hash)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (p PublicStruct) Encrypt(content string) (string, error) {
|
|||
|
|
b, err := rsa.EncryptPKCS1v15(rand.Reader, p.publicKey, []byte(content))
|
|||
|
|
if err != nil {
|
|||
|
|
return "", err
|
|||
|
|
}
|
|||
|
|
return base64.StdEncoding.EncodeToString(b), nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func NewPublicRSA(key string) (p PublicStruct, err error) {
|
|||
|
|
priKey, err := ParsePublicKey(key)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
p.publicKey = priKey
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type PrivateStruct struct {
|
|||
|
|
privateKey *rsa.PrivateKey
|
|||
|
|
PublicStruct
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (p PrivateStruct) Sign(content string, hash crypto.Hash) (string, error) {
|
|||
|
|
return Sign(content, p.privateKey, hash)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (p PrivateStruct) Decrypt(content string) (string, error) {
|
|||
|
|
bcontent, err := base64.StdEncoding.DecodeString(content)
|
|||
|
|
if err != nil {
|
|||
|
|
return "", err
|
|||
|
|
}
|
|||
|
|
b, err := rsa.DecryptPKCS1v15(rand.Reader, p.privateKey, bcontent)
|
|||
|
|
if err != nil {
|
|||
|
|
return "", err
|
|||
|
|
}
|
|||
|
|
return string(b), nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func NewPrivateRSA(key string) (p PrivateStruct, err error) {
|
|||
|
|
priKey, err := ParsePrivateKey(key)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
p.privateKey = priKey
|
|||
|
|
p.publicKey = &priKey.PublicKey
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func NewPrivateRSAPfx(key, password string) (p PrivateStruct, err error) {
|
|||
|
|
priKey, err := ParsePrivateKeyPfx(key, password)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
p.privateKey = priKey
|
|||
|
|
p.publicKey = &priKey.PublicKey
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func Sign(signContent string, privateKey *rsa.PrivateKey, hash crypto.Hash) (string, error) {
|
|||
|
|
h := hash.New()
|
|||
|
|
h.Write([]byte(signContent))
|
|||
|
|
hashed := h.Sum(nil)
|
|||
|
|
|
|||
|
|
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, hash, hashed)
|
|||
|
|
if err != nil {
|
|||
|
|
panic(err)
|
|||
|
|
}
|
|||
|
|
return base64.StdEncoding.EncodeToString(signature), nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func Verify(sign, content string, publicKey *rsa.PublicKey, hash crypto.Hash) error {
|
|||
|
|
h := hash.New()
|
|||
|
|
h.Write([]byte(content))
|
|||
|
|
hashed := h.Sum(nil)
|
|||
|
|
sig, _ := base64.StdEncoding.DecodeString(sign)
|
|||
|
|
return rsa.VerifyPKCS1v15(publicKey, hash, hashed, sig)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ParsePrivateKey(privateKey string) (*rsa.PrivateKey, error) {
|
|||
|
|
privateKey = FormatPrivateKey(privateKey)
|
|||
|
|
// 2、解码私钥字节,生成加密对象
|
|||
|
|
block, _ := pem.Decode([]byte(privateKey))
|
|||
|
|
if block == nil {
|
|||
|
|
return nil, errors.New("private key info error")
|
|||
|
|
}
|
|||
|
|
// 3、解析DER编码的私钥,生成私钥对象
|
|||
|
|
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return priKey, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ParsePublicKey(publicKey string) (*rsa.PublicKey, error) {
|
|||
|
|
publicKey = FormatPublicKey(publicKey)
|
|||
|
|
// 2、解码私钥字节,生成加密对象
|
|||
|
|
block, _ := pem.Decode([]byte(publicKey))
|
|||
|
|
if block == nil {
|
|||
|
|
return nil, errors.New("public key info error")
|
|||
|
|
}
|
|||
|
|
// 3、解析DER编码的私钥,生成公钥对象
|
|||
|
|
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return pubKey.(*rsa.PublicKey), nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func FormatPrivateKey(privateKey string) string {
|
|||
|
|
if !strings.HasPrefix(privateKey, PRIVATE_PEM_BEGIN) {
|
|||
|
|
privateKey = PRIVATE_PEM_BEGIN + privateKey
|
|||
|
|
}
|
|||
|
|
if !strings.HasSuffix(privateKey, PRIVATE_PEM_END) {
|
|||
|
|
privateKey = privateKey + PRIVATE_PEM_END
|
|||
|
|
}
|
|||
|
|
return privateKey
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func FormatPublicKey(publicKey string) string {
|
|||
|
|
if !strings.HasPrefix(publicKey, PUBLIC_PEM_BEGIN) {
|
|||
|
|
publicKey = PUBLIC_PEM_BEGIN + publicKey
|
|||
|
|
}
|
|||
|
|
if !strings.HasSuffix(publicKey, PUBLIC_PEM_END) {
|
|||
|
|
publicKey = publicKey + PUBLIC_PEM_END
|
|||
|
|
}
|
|||
|
|
return publicKey
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ParsePrivateKeyPfx(privateKeyName, privatePassword string) (*rsa.PrivateKey, error) {
|
|||
|
|
f, err := os.Open(privateKeyName)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bytes, err := ioutil.ReadAll(f)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
// 因为pfx证书公钥和密钥是成对的,所以要先转成pem.Block
|
|||
|
|
blocks, err := pkcs12.ToPEM(bytes, privatePassword)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
//if len(blocks) != 2 {
|
|||
|
|
// return nil, errors.New("解密错误")
|
|||
|
|
//}
|
|||
|
|
// 拿到第一个block,用x509解析出私钥(当然公钥也是可以的)
|
|||
|
|
privateKey, err := x509.ParsePKCS1PrivateKey(blocks[0].Bytes)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return privateKey, nil
|
|||
|
|
}
|