tkcashgame_v4/pkg/xcrypto/rsa.go

185 lines
4.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}