1
0
mirror of https://github.com/charlienet/go-mixed.git synced 2025-07-17 16:12:42 +08:00
Files
go-mixed/crypto/rsa.go
2022-05-06 17:29:35 +08:00

135 lines
2.4 KiB
Go

package crypto
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"strconv"
)
var _ IAsymmetric = &rsaInstance{}
type rsaInstance struct {
hashOptions
prk *rsa.PrivateKey
puk *rsa.PublicKey
}
type rsaOption func(o *rsaInstance) error
func NewRsa(h Hash, opts ...rsaOption) (*rsaInstance, error) {
o := &rsaInstance{}
sh := crypto.Hash(h)
if !sh.Available() {
return nil, errors.New("unknown hash value " + strconv.Itoa(int(h)))
}
o.h = sh
for _, f := range opts {
if err := f(o); err != nil {
return nil, err
}
}
// 未设置私钥时随机生成密钥
if o.prk == nil {
prk, err := rsa.GenerateKey(rand.Reader, defaultRsaBits)
if err != nil {
return nil, err
}
o.prk = prk
}
// 公钥未设置时从私钥导出
if o.puk == nil {
o.puk = &o.prk.PublicKey
}
return o, nil
}
func ParsePKCS8PrivateKey(p []byte) rsaOption {
return func(o *rsaInstance) error {
block, _ := pem.Decode(p)
if block == nil {
return errors.New("failed to decode private key")
}
prk, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return err
}
o.prk = prk.(*rsa.PrivateKey)
return nil
}
}
func ParsePKCS1PrivateKey(p []byte) rsaOption {
return func(o *rsaInstance) error {
block, _ := pem.Decode(p)
if block == nil {
return errors.New("failed to decode private key")
}
prk, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return err
}
o.prk = prk
return nil
}
}
func ParsePKIXPublicKey(p []byte) rsaOption {
return func(o *rsaInstance) error {
block, _ := pem.Decode(p)
if block == nil {
return errors.New("failed to decode public key")
}
k, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return err
}
puk := k.(*rsa.PublicKey)
o.puk = puk
return nil
}
}
func (o *rsaInstance) Encrypt(msg []byte) ([]byte, error) {
return rsa.EncryptPKCS1v15(rand.Reader, o.puk, msg)
}
func (o *rsaInstance) Decrypt(ciphertext []byte) ([]byte, error) {
return rsa.DecryptPKCS1v15(rand.Reader, o.prk, ciphertext)
}
func (o *rsaInstance) Sign(msg []byte) ([]byte, error) {
hashed := o.getHash(msg)
sign, err := rsa.SignPKCS1v15(rand.Reader, o.prk, o.h, hashed)
return sign, err
}
func (o *rsaInstance) Verify(msg, sign []byte) bool {
hashed := o.getHash(msg)
if err := rsa.VerifyPKCS1v15(o.puk, o.h, hashed, sign); err != nil {
return false
}
return true
}