feat(crypto):完成RSA加密算法功能。
This commit is contained in:
		
							
								
								
									
										67
									
								
								encryption/rsa/errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								encryption/rsa/errors.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
package rsa
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
type UnableToGenerateKeyPairError struct {
 | 
			
		||||
	err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *UnableToGenerateKeyPairError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("未能生成密钥对, %s", e.err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type AbsentPrivateKeyError struct{}
 | 
			
		||||
 | 
			
		||||
func (e *AbsentPrivateKeyError) Error() string {
 | 
			
		||||
	return "缺少私钥"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type AbsentPublicKeyError struct{}
 | 
			
		||||
 | 
			
		||||
func (e *AbsentPublicKeyError) Error() string {
 | 
			
		||||
	return "缺少公钥"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type EncryptionError struct {
 | 
			
		||||
	err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *EncryptionError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("加密失败, %s", e.err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type DecryptionError struct {
 | 
			
		||||
	err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *DecryptionError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("解密失败, %s", e.err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type KeyNotFoundError struct{}
 | 
			
		||||
 | 
			
		||||
func (e *KeyNotFoundError) Error() string {
 | 
			
		||||
	return "找不到密钥"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type InvalidSignMethodError struct{}
 | 
			
		||||
 | 
			
		||||
func (e *InvalidSignMethodError) Error() string {
 | 
			
		||||
	return "无效的签名方法"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SignError struct {
 | 
			
		||||
	err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *SignError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("签名失败, %s", e.err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type VerifyError struct {
 | 
			
		||||
	err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *VerifyError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("验证失败, %s", e.err)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										141
									
								
								encryption/rsa/key.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								encryption/rsa/key.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
package rsa
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"encoding/pem"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type KeyFormat int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	RSA KeyFormat = iota
 | 
			
		||||
	COMMON
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 将指定的私钥编码为PEM格式,如果不指定具体格式将使用RSA PRIVATE KEY(PKCS1)格式。
 | 
			
		||||
func EncodePrivateKey(key *rsa.PrivateKey, format ...KeyFormat) ([]byte, error) {
 | 
			
		||||
	var block *pem.Block
 | 
			
		||||
	switch append(format, RSA)[0] {
 | 
			
		||||
	case COMMON:
 | 
			
		||||
		key, err := x509.MarshalPKCS8PrivateKey(key)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("不支持的私钥格式,%w", err)
 | 
			
		||||
		}
 | 
			
		||||
		block = &pem.Block{
 | 
			
		||||
			Type:  "PRIVATE KEY",
 | 
			
		||||
			Bytes: key,
 | 
			
		||||
		}
 | 
			
		||||
	case RSA:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	default:
 | 
			
		||||
		key := x509.MarshalPKCS1PrivateKey(key)
 | 
			
		||||
		block = &pem.Block{
 | 
			
		||||
			Type:  "RSA PRIVATE KEY",
 | 
			
		||||
			Bytes: key,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return pem.EncodeToMemory(block), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 将指定的公钥编码为PEM格式,如果不指定具体格式将使用RSA PUBLIC KEY(PKCS1)格式。
 | 
			
		||||
func EncodePublicKey(key *rsa.PublicKey, format ...KeyFormat) ([]byte, error) {
 | 
			
		||||
	var block *pem.Block
 | 
			
		||||
	switch append(format, RSA)[0] {
 | 
			
		||||
	case COMMON:
 | 
			
		||||
		key, err := x509.MarshalPKIXPublicKey(key)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("不支持的公钥格式,%w", err)
 | 
			
		||||
		}
 | 
			
		||||
		block = &pem.Block{
 | 
			
		||||
			Type:  "PUBLIC KEY",
 | 
			
		||||
			Bytes: key,
 | 
			
		||||
		}
 | 
			
		||||
	case RSA:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	default:
 | 
			
		||||
		key := x509.MarshalPKCS1PublicKey(key)
 | 
			
		||||
		block = &pem.Block{
 | 
			
		||||
			Type:  "RSA PUBLIC KEY",
 | 
			
		||||
			Bytes: key,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return pem.EncodeToMemory(block), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 将给定的PEM证书内容解析为RSA私钥。
 | 
			
		||||
// 仅能读取PEM证书中的第一个私钥编码段。
 | 
			
		||||
func DecodePrivateKey(cert []byte) (*rsa.PrivateKey, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		block          *pem.Block
 | 
			
		||||
		pemRestContent = cert
 | 
			
		||||
	)
 | 
			
		||||
	for {
 | 
			
		||||
		block, pemRestContent = pem.Decode(pemRestContent)
 | 
			
		||||
		if block == nil {
 | 
			
		||||
			return nil, &KeyNotFoundError{}
 | 
			
		||||
		}
 | 
			
		||||
		if block.Type == "PRIVATE KEY" || block.Type == "RSA PRIVATE KEY" {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	switch block.Type {
 | 
			
		||||
	case "PRIVATE KEY":
 | 
			
		||||
		key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("不支持的私钥格式,%w", err)
 | 
			
		||||
		}
 | 
			
		||||
		pKey, ok := key.(*rsa.PrivateKey)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, fmt.Errorf("提供的私钥不是RSA专用私钥,%w", err)
 | 
			
		||||
		}
 | 
			
		||||
		return pKey, nil
 | 
			
		||||
	case "RSA PRIVATE KEY":
 | 
			
		||||
		key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("不支持的私钥格式,%w", err)
 | 
			
		||||
		}
 | 
			
		||||
		return key, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("不支持的私钥格式或者私钥不存在,%s", block.Type)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 将给定的PEM证书内容解析为RSA公钥。
 | 
			
		||||
// 仅能读取PEM证书中的第一个公钥编码段。
 | 
			
		||||
func DecodePublicKey(cert []byte) (*rsa.PublicKey, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		block          *pem.Block
 | 
			
		||||
		pemRestContent = cert
 | 
			
		||||
	)
 | 
			
		||||
	for {
 | 
			
		||||
		block, pemRestContent = pem.Decode(pemRestContent)
 | 
			
		||||
		if block == nil {
 | 
			
		||||
			return nil, &KeyNotFoundError{}
 | 
			
		||||
		}
 | 
			
		||||
		if block.Type == "PUBLIC KEY" || block.Type == "RSA PUBLIC KEY" {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	switch block.Type {
 | 
			
		||||
	case "PUBLIC KEY":
 | 
			
		||||
		key, err := x509.ParsePKIXPublicKey(block.Bytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("不支持的公钥格式,%w", err)
 | 
			
		||||
		}
 | 
			
		||||
		pKey, ok := key.(*rsa.PublicKey)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, fmt.Errorf("提供的公钥不是RSA专用公钥,%w", err)
 | 
			
		||||
		}
 | 
			
		||||
		return pKey, nil
 | 
			
		||||
	case "RSA PUBLIC KEY":
 | 
			
		||||
		key, err := x509.ParsePKCS1PublicKey(block.Bytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("不支持的公钥格式,%w", err)
 | 
			
		||||
		}
 | 
			
		||||
		return key, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("不支持的公钥格式或者公钥不存在,%s", block.Type)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										181
									
								
								encryption/rsa/rsa.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								encryption/rsa/rsa.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,181 @@
 | 
			
		||||
// 提供RSA不对称加解密功能。
 | 
			
		||||
package rsa
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto"
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"crypto/sha512"
 | 
			
		||||
	"errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type KeyLength int
 | 
			
		||||
type SignAlgorithm int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	RSA1024 KeyLength = 1024
 | 
			
		||||
	RSA2048 KeyLength = 2048
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	PSSSign SignAlgorithm = iota
 | 
			
		||||
	PKCS1Sign
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type KeyPair struct {
 | 
			
		||||
	PublicKey  *rsa.PublicKey
 | 
			
		||||
	PrivateKey *rsa.PrivateKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 生成一个新的RSA密钥对。
 | 
			
		||||
func NewKeyPair(length KeyLength) (*KeyPair, error) {
 | 
			
		||||
	privateKey, err := rsa.GenerateKey(rand.Reader, int(length))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, &UnableToGenerateKeyPairError{err: err}
 | 
			
		||||
	}
 | 
			
		||||
	publicKey := privateKey.Public().(*rsa.PublicKey)
 | 
			
		||||
	return &KeyPair{
 | 
			
		||||
		PublicKey:  publicKey,
 | 
			
		||||
		PrivateKey: privateKey,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 从一个PEM格式的密钥对中读取一套RSA密钥对。
 | 
			
		||||
// 如果获取到的公钥与私钥不配对,那么将自动使用私钥生成一个配对的公钥,以保证密钥对的完整性。
 | 
			
		||||
// 如果提供的证书中只存在公钥,那么将会保持私钥为空。
 | 
			
		||||
func NewFromPEM(cert []byte) (*KeyPair, error) {
 | 
			
		||||
	publicKey, err := DecodePublicKey(cert)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, &KeyNotFoundError{}) {
 | 
			
		||||
			publicKey = nil
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	privateKey, err := DecodePrivateKey(cert)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, &KeyNotFoundError{}) {
 | 
			
		||||
			privateKey = nil
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if privateKey != nil {
 | 
			
		||||
		pubKeyFromPriKey := privateKey.Public().(*rsa.PublicKey)
 | 
			
		||||
		if publicKey == nil || !publicKey.Equal(pubKeyFromPriKey) {
 | 
			
		||||
			publicKey = pubKeyFromPriKey
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &KeyPair{
 | 
			
		||||
		PublicKey:  publicKey,
 | 
			
		||||
		PrivateKey: privateKey,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 加载一个新的公钥,将会自动清空私钥。
 | 
			
		||||
func (kp *KeyPair) LoadPublicKey(cert []byte) error {
 | 
			
		||||
	publicKey, err := DecodePublicKey(cert)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	kp.PublicKey = publicKey
 | 
			
		||||
	kp.PrivateKey = nil
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 加载一个私钥,将会自动生成一个配对的公钥。
 | 
			
		||||
func (kp *KeyPair) LoadPrivateKey(cert []byte) error {
 | 
			
		||||
	privateKey, err := DecodePrivateKey(cert)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	kp.PrivateKey = privateKey
 | 
			
		||||
	kp.PublicKey = privateKey.Public().(*rsa.PublicKey)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 使用密钥对加密给定的数据,如果密钥对中不存在公钥则会返回错误。
 | 
			
		||||
func (kp KeyPair) Encrypt(data []byte, label ...[]byte) ([]byte, error) {
 | 
			
		||||
	if kp.PublicKey == nil {
 | 
			
		||||
		return nil, &AbsentPublicKeyError{}
 | 
			
		||||
	}
 | 
			
		||||
	var cipherLabel []byte
 | 
			
		||||
	if len(label) > 0 {
 | 
			
		||||
		cipherLabel = label[0]
 | 
			
		||||
	} else {
 | 
			
		||||
		cipherLabel = nil
 | 
			
		||||
	}
 | 
			
		||||
	hasher := sha512.New()
 | 
			
		||||
	cipherText, err := rsa.EncryptOAEP(hasher, rand.Reader, kp.PublicKey, data, cipherLabel)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, &EncryptionError{err: err}
 | 
			
		||||
	}
 | 
			
		||||
	return cipherText, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 使用密钥对解密给定的数据,如果密钥对中不存在私钥则会返回错误。
 | 
			
		||||
func (kp KeyPair) Decrypt(data []byte, label ...[]byte) ([]byte, error) {
 | 
			
		||||
	if kp.PrivateKey == nil {
 | 
			
		||||
		return nil, &AbsentPrivateKeyError{}
 | 
			
		||||
	}
 | 
			
		||||
	var cipherLabel []byte
 | 
			
		||||
	if len(label) > 0 {
 | 
			
		||||
		cipherLabel = label[0]
 | 
			
		||||
	} else {
 | 
			
		||||
		cipherLabel = nil
 | 
			
		||||
	}
 | 
			
		||||
	hasher := sha512.New()
 | 
			
		||||
	plainText, err := rsa.DecryptOAEP(hasher, rand.Reader, kp.PrivateKey, data, cipherLabel)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, &DecryptionError{err: err}
 | 
			
		||||
	}
 | 
			
		||||
	return plainText, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 对给定的数据使用私钥进行签名。
 | 
			
		||||
func (kp KeyPair) Sign(data []byte, algorithm ...SignAlgorithm) ([]byte, error) {
 | 
			
		||||
	if kp.PrivateKey == nil {
 | 
			
		||||
		return nil, &AbsentPrivateKeyError{}
 | 
			
		||||
	}
 | 
			
		||||
	hashedData := sha512.Sum512(data)
 | 
			
		||||
	switch append(algorithm, PSSSign)[0] {
 | 
			
		||||
	case PSSSign:
 | 
			
		||||
		signature, err := rsa.SignPSS(rand.Reader, kp.PrivateKey, crypto.SHA512, hashedData[:], &rsa.PSSOptions{SaltLength: 64})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, &SignError{err: err}
 | 
			
		||||
		}
 | 
			
		||||
		return signature, nil
 | 
			
		||||
	case PKCS1Sign:
 | 
			
		||||
		signature, err := rsa.SignPKCS1v15(rand.Reader, kp.PrivateKey, crypto.SHA512, hashedData[:])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, &SignError{err: err}
 | 
			
		||||
		}
 | 
			
		||||
		return signature, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, &InvalidSignMethodError{}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 对给定的数据和签名数据使用公钥进行验证。不返回任何错误信息即表示验证成功。
 | 
			
		||||
func (kp KeyPair) Verify(data, signature []byte, algorithm ...SignAlgorithm) error {
 | 
			
		||||
	if kp.PublicKey == nil {
 | 
			
		||||
		return &AbsentPublicKeyError{}
 | 
			
		||||
	}
 | 
			
		||||
	hashedData := sha512.Sum512(data)
 | 
			
		||||
	switch append(algorithm, PSSSign)[0] {
 | 
			
		||||
	case PSSSign:
 | 
			
		||||
		err := rsa.VerifyPSS(kp.PublicKey, crypto.SHA512, hashedData[:], signature, &rsa.PSSOptions{SaltLength: 64})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &VerifyError{err: err}
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	case PKCS1Sign:
 | 
			
		||||
		err := rsa.VerifyPKCS1v15(kp.PublicKey, crypto.SHA512, hashedData[:], signature)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &VerifyError{err: err}
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	default:
 | 
			
		||||
		return &InvalidSignMethodError{}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user