mirror of
https://github.com/charlienet/go-mixed.git
synced 2025-07-17 16:12:42 +08:00
135 lines
2.4 KiB
Go
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
|
|
}
|