Skip to content

Commit

Permalink
Feature/cryptoUtil rsa (#62)
Browse files Browse the repository at this point in the history
* feat: rsa crypto

* feat: update

* feat: TestGenerateRSAKeys

* feat: TestGenerateRSAKeysError
  • Loading branch information
jefferyjob authored Mar 15, 2024
1 parent 1ee9ff4 commit 230b885
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 0 deletions.
9 changes: 9 additions & 0 deletions README.cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,15 @@ func HashSHA256(str string) string

// Md5 MD5加密
func Md5(string string) string

// GenerateRSAKeys 生成RSA私钥和公钥
func GenerateRSAKeys() (string, string, error)

// EncryptRSA RSA加密数据
func EncryptRSA(publicKeyStr string, message []byte) ([]byte, error)

// DecryptRSA RSA解密数据
func DecryptRSA(privateKeyStr string, ciphertext []byte) ([]byte, error)
```

### byteUtil 字节数组
Expand Down
9 changes: 9 additions & 0 deletions cryptoUtil/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,13 @@ func HashSHA256(str string) string

// Md5 MD5加密
func Md5(str string) string

// GenerateRSAKeys 生成RSA私钥和公钥
func GenerateRSAKeys() (string, string, error)

// EncryptRSA RSA加密数据
func EncryptRSA(publicKeyStr string, message []byte) ([]byte, error)

// DecryptRSA RSA解密数据
func DecryptRSA(privateKeyStr string, ciphertext []byte) ([]byte, error)
```
90 changes: 90 additions & 0 deletions cryptoUtil/rsa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package cryptoUtil

import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
)

// GenerateRSAKeys 生成RSA私钥和公钥
func GenerateRSAKeys() (string, string, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return "", "", err
}

publicKey := &privateKey.PublicKey

// 将私钥转换为PEM格式
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyBytes,
})

// 将公钥转换为PEM格式
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return "", "", err
}
publicKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: publicKeyBytes,
})

return string(privateKeyPEM), string(publicKeyPEM), nil
}

// EncryptRSA RSA加密数据
func EncryptRSA(publicKeyStr string, message []byte) ([]byte, error) {
// 解码公钥
publicKeyBlock, _ := pem.Decode([]byte(publicKeyStr))
if publicKeyBlock == nil {
return nil, fmt.Errorf("failed to parse public key")
}

// 解析公钥
publicKey, err := x509.ParsePKIXPublicKey(publicKeyBlock.Bytes)
if err != nil {
return nil, err
}

// 类型断言为RSA公钥
rsaPublicKey, ok := publicKey.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("failed to convert public key to RSA public key")
}

// 加密消息
ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, message)
if err != nil {
return nil, err
}

return ciphertext, nil
}

// DecryptRSA RSA解密数据
func DecryptRSA(privateKeyStr string, ciphertext []byte) ([]byte, error) {
// 解码私钥
privateKeyBlock, _ := pem.Decode([]byte(privateKeyStr))
if privateKeyBlock == nil {
return nil, fmt.Errorf("failed to parse private key")
}

// 解析私钥
privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
if err != nil {
return nil, err
}

// 解密密文
plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, ciphertext)
if err != nil {
return nil, err
}

return plaintext, nil
}
122 changes: 122 additions & 0 deletions cryptoUtil/rsa_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package cryptoUtil

import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"reflect"
"testing"
)

// 测试 rsa.GenerateKey 生产失败
func TestGenerateRSAKeysError(t *testing.T) {
// 保存原始的 rand.Reader
originalRandReader := rand.Reader

// 替换全局的 rand.Reader 为一个模拟错误的 Reader
rand.Reader = &badRandomReader{}

// 恢复原始的 rand.Reader
defer func() {
rand.Reader = originalRandReader
}()

privateKeyPEM, publicKeyPEM, err := GenerateRSAKeys()

// 检查返回的错误是否符合预期
expectedErr := errors.New("fake error")
if err == nil || err.Error() != expectedErr.Error() {
t.Errorf("Expected error '%v' but got '%v'", expectedErr, err)
}

// 检查返回的 PEM 字符串是否为空
if privateKeyPEM != "" {
t.Error("Expected empty private key PEM string")
}

if publicKeyPEM != "" {
t.Error("Expected empty public key PEM string")
}
}

// 伪造一个读取器,用来模拟产生错误的情况
type badRandomReader struct{}

func (r *badRandomReader) Read([]byte) (int, error) {
return 0, errors.New("fake error")
}

// 测试RAS公钥和私钥生成
func TestGenerateRSAKeys(t *testing.T) {
privateKeyPEM, publicKeyPEM, err := GenerateRSAKeys()
if err != nil {
t.Errorf("GenerateRSAKeys() error = %v", err)
return
}

// 解码私钥 PEM 格式
block, _ := pem.Decode([]byte(privateKeyPEM))
if block == nil || block.Type != "RSA PRIVATE KEY" {
t.Errorf("Invalid private key PEM")
return
}
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
t.Errorf("Failed to parse private key: %v", err)
return
}

// 解码公钥 PEM 格式
block, _ = pem.Decode([]byte(publicKeyPEM))
if block == nil || block.Type != "RSA PUBLIC KEY" {
t.Errorf("Invalid public key PEM")
return
}
publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
t.Errorf("Failed to parse public key: %v", err)
return
}
rsaPublicKey, ok := publicKey.(*rsa.PublicKey)
if !ok {
t.Errorf("Failed to convert public key to RSA public key")
return
}

// 比较生成的密钥与解析的密钥
if !reflect.DeepEqual(privateKey.Public(), rsaPublicKey) {
t.Errorf("Generated private key does not match parsed public key")
return
}
}

func TestRSAEncryptionAndDecryption(t *testing.T) {
// 生成RSA密钥对
privateKey, publicKey, err := GenerateRSAKeys()
if err != nil {
t.Errorf("Failed to generate RSA keys: %s", err)
return
}

// 加密数据
plaintext := []byte("Hello, RSA!")
ciphertext, err := EncryptRSA(publicKey, plaintext)
if err != nil {
t.Errorf("Failed to encrypt data: %s", err)
return
}

// 解密数据
decryptedText, err := DecryptRSA(privateKey, ciphertext)
if err != nil {
t.Errorf("Failed to decrypt data: %s", err)
return
}

// 检查解密后的数据是否与原始数据一致
if string(decryptedText) != string(plaintext) {
t.Errorf("Decrypted text does not match the original plaintext")
}
}

0 comments on commit 230b885

Please sign in to comment.