feat(crypto):完成RSA加密算法功能。
This commit is contained in:
parent
b004e952c4
commit
5e284f320d
11
README.md
11
README.md
@ -16,11 +16,12 @@ Golang 中可以使用的常用辅助功能工具箱。主要配备以下功能
|
|||||||
- [x] No Padding
|
- [x] No Padding
|
||||||
- [x] ZerosPadding
|
- [x] ZerosPadding
|
||||||
- [x] Pkcs7Padding
|
- [x] Pkcs7Padding
|
||||||
- [ ] RSA 加解密算法
|
- [x] RSA 加解密算法
|
||||||
- [ ] 1024 位长
|
- [x] 1024 位长
|
||||||
- [ ] 2048 位长
|
- [x] 2048 位长
|
||||||
- [ ] KeyPair 生成器
|
- [x] KeyPair 生成器
|
||||||
- [ ] RSA 签名算法
|
- [x] Key 导入与导出
|
||||||
|
- [x] RSA 签名算法
|
||||||
- 散列及校验和算法。
|
- 散列及校验和算法。
|
||||||
- [x] Sha512 散列算法
|
- [x] Sha512 散列算法
|
||||||
- [x] Sha256 散列算法
|
- [x] Sha256 散列算法
|
||||||
|
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{}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user