diff --git a/README.cn.md b/README.cn.md index 1151923..5cc3b23 100644 --- a/README.cn.md +++ b/README.cn.md @@ -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 字节数组 diff --git a/cryptoUtil/README.md b/cryptoUtil/README.md index 395b3e3..5719d38 100644 --- a/cryptoUtil/README.md +++ b/cryptoUtil/README.md @@ -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) ``` \ No newline at end of file diff --git a/cryptoUtil/rsa.go b/cryptoUtil/rsa.go new file mode 100644 index 0000000..86411ad --- /dev/null +++ b/cryptoUtil/rsa.go @@ -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 +} diff --git a/cryptoUtil/rsa_test.go b/cryptoUtil/rsa_test.go new file mode 100644 index 0000000..ec0b81c --- /dev/null +++ b/cryptoUtil/rsa_test.go @@ -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") + } +}