go rsa加密和解密 签名和验证
网上关于rsa的用法很多,尤其是 https://cloud.tencent.com/developer/section/1140761,但是上面的例子不全面
package utils import ( "bytes" "crypto" "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/hex" "encoding/pem" "fmt" "os" ) func RSAEncryptOAEP(publicKeypem, labeltext, plaintext string) (ciphertext string) { publicBlock, _ := pem.Decode([]byte(publicKeypem)) if publicBlock == nil { panic("public key error") } pub, err := x509.ParsePKIXPublicKey(publicBlock.Bytes) if err != nil { panic("publicKey is not *rsa.PublicKey") } publicKey := pub.(*rsa.PublicKey) rng := rand.Reader secretMessage := []byte(plaintext) label := []byte(labeltext) cipherbyte, err := rsa.EncryptOAEP(sha256.New(), rng, publicKey, secretMessage, label) if err != nil { panic(fmt.Sprintf("Error from encryption: %s\n", err)) } // 由于加密是随机函数,密文将是 // 每次都不一样。 //fmt.Printf("Ciphertext: %x\n", cipherbyte) ciphertext = fmt.Sprintf("%x\n", cipherbyte) return } func RSADecryptOAEP(privateKeypem, labeltext, ciphertext string) (plaintext string) { privateBlock, _ := pem.Decode([]byte(privateKeypem)) if privateBlock == nil { panic("private key error") } privateKey, err := x509.ParsePKCS1PrivateKey(privateBlock.Bytes) if err != nil { panic("privateKey is not *rsa.PrivateKey") } /* prkI, err := x509.ParsePKCS8PrivateKey(privateBlock.Bytes) if err != nil { panic("privateKey is not *rsa.PrivateKey") } privateKey := prkI.(*rsa.PrivateKey) */ rng := rand.Reader /// cipherByte, _ := hex.DecodeString(ciphertext) label := []byte(labeltext) plainbyte, err := rsa.DecryptOAEP(sha256.New(), rng, privateKey, cipherByte, label) if err != nil { panic(fmt.Sprintf("Error decrypting: %s\n", err)) } // 由于加密是随机函数,密文将是 // 每次都不一样。 plaintext = string(plainbyte) return } func RSAEncryptPKCS1v15(publicKeypem, plaintext string) (ciphertext string) { publicBlock, _ := pem.Decode([]byte(publicKeypem)) if publicBlock == nil { panic("public key error") } pub, err := x509.ParsePKIXPublicKey(publicBlock.Bytes) if err != nil { panic("publicKey is not *rsa.PublicKey") } publicKey := pub.(*rsa.PublicKey) plaintbyte := []byte(plaintext) blocks := pkcs1Padding(plaintbyte, publicKey.N.BitLen()/8) buffer := bytes.Buffer{} for _, block := range blocks { ciphertextPart, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, block) if err != nil { panic(fmt.Sprintf("Error EncryptPKCS1v15: %s\n", err)) } buffer.Write(ciphertextPart) } ciphertext = fmt.Sprintf("%x\n", buffer.Bytes()) return } func RSADecryptPKCS1v15(privateKeypem, ciphertext string) (plaintext string) { privateBlock, _ := pem.Decode([]byte(privateKeypem)) if privateBlock == nil { panic("private key error") } privateKey, err := x509.ParsePKCS1PrivateKey(privateBlock.Bytes) if err != nil { panic("privateKey is not *rsa.PrivateKey") } /* prkI, err := x509.ParsePKCS8PrivateKey(privateBlock.Bytes) if err != nil { panic("privateKey is not *rsa.PrivateKey") } privateKey := prkI.(*rsa.PrivateKey) */ /// cipherByte, _ := hex.DecodeString(ciphertext) ciphertextBlocks := unPadding(cipherByte, privateKey.N.BitLen()/8) buffer := bytes.Buffer{} for _, ciphertextBlock := range ciphertextBlocks { plaintextBlock, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, ciphertextBlock) if err != nil { panic(fmt.Sprintf("Error DecryptPKCS1v15: %s\n", err)) } buffer.Write(plaintextBlock) } plaintext = string(buffer.Bytes()) return } func SignPKCS1v15(privateKeypem string, src []byte, hash crypto.Hash) ([]byte, error) { privateBlock, _ := pem.Decode([]byte(privateKeypem)) if privateBlock == nil { panic("private key error") } privateKey, err := x509.ParsePKCS1PrivateKey(privateBlock.Bytes) if err != nil { panic("privateKey is not *rsa.PrivateKey") } h := hash.New() h.Write(src) hashed := h.Sum(nil) return rsa.SignPKCS1v15(rand.Reader, privateKey, hash, hashed) } func VerifyPKCS1v15Verify(publicKeypem string, src []byte, sign []byte, hash crypto.Hash) error { publicBlock, _ := pem.Decode([]byte(publicKeypem)) if publicBlock == nil { panic("public key error") } pub, err := x509.ParsePKIXPublicKey(publicBlock.Bytes) if err != nil { panic("publicKey is not *rsa.PublicKey") } publicKey := pub.(*rsa.PublicKey) h := hash.New() h.Write(src) hashed := h.Sum(nil) return rsa.VerifyPKCS1v15(publicKey, hash, hashed, sign) } func pkcs1Padding(src []byte, keySize int) [][]byte { srcSize := len(src) blockSize := keySize - 11 var v [][]byte if srcSize <= blockSize { v = append(v, src) } else { groups := len(src) / blockSize for i := 0; i < groups; i++ { block := src[:blockSize] v = append(v, block) src = src[blockSize:] if len(src) < blockSize { v = append(v, src) } } } return v } func unPadding(src []byte, keySize int) [][]byte { srcSize := len(src) blockSize := keySize var v [][]byte if srcSize == blockSize { v = append(v, src) } else { groups := len(src) / blockSize for i := 0; i < groups; i++ { block := src[:blockSize] v = append(v, block) src = src[blockSize:] } } return v } //RSA公钥私钥产生 GenRsaKey(1024) func GenRsaKey(bits int) error { // 生成私钥文件 privateKey, err := rsa.GenerateKey(rand.Reader, bits) if err != nil { return err } derStream := x509.MarshalPKCS1PrivateKey(privateKey) block := &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: derStream, } file, err := os.Create("private.pem") if err != nil { return err } err = pem.Encode(file, block) if err != nil { return err } // 生成公钥文件 publicKey := &privateKey.PublicKey derPkix, err := x509.MarshalPKIXPublicKey(publicKey) if err != nil { return err } block = &pem.Block{ Type: "PUBLIC KEY", Bytes: derPkix, } file, err = os.Create("public.pem") if err != nil { return err } err = pem.Encode(file, block) if err != nil { return err } return nil }
使用如下:
pirvatekey := "-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKBgQDXmqwFmi9TPVL1NgYZgGaHdPz7ZsskAOukaYg/hZkAn4rj8JJcaE/DzRy707bq6YBUpp+1ssiaadJRKR6+XMSzdyJz44Vl5rrArExrzGiNry+txRVo00U4xbIrmMX+aRKvPQ/xJ7xkxRhdxsY4F/wMcWDyJS+eyxJkHiBrHJ3ciQIDAQABAoGBAJV7eZUQx4sQ03mLkUMREQUNiXDMXj+CG96MBJj2CZSzCNrsqq1C7Tq19RwMt5+7cOw/8i9J22ejwtvehKA7NWxpsUBC+lDqXk3FCvtbL3d2fcARdh/1zWZN9WRvafkVPNPAeRC6ARp63DOe8FkT0C22DTOd0Xyvo0Zp7pF/GjXhAkEA/BkAFlV/4jHEglyXHNGrReMjClw2ClqKK5VXIk6UCJfVaGNDGbfw0ueYFnnOeIo8GPhgVjSC4wU2rX89pSFxTQJBANrxDqKc6wFw1jGpmxI25inxYTvA3SuSk36b4CSrRL7w3g9r+6QQfAlpBRZ9NBCL9WHeWHtgauxeDGJB2kmXui0CQQDhadlSHxFCSA3WIsRb2H609uwWD22ixGJXpilLW8eyB1GjDV6qWHbVno+3SSL9VV13Vl+NtVZzd+30JJoSVVzhAkB8sISxP8TnUSfrqLhUK0fx4zKJIVHUmum9VXDV8WR5ihwtlEYALhM2GMV5BV09fzgEwOiLe2Hps7ZBz1dOSkcRAkEA+D3kzvNpEYtqpjGHfUCxwmu/BwathDo09vj+gCcjhoJh/ADpa8+a0RQA6vcVMges0UcmIiIyQPNzCGlLBXtl9A==\n-----END RSA PRIVATE KEY-----" pubKey := "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXmqwFmi9TPVL1NgYZgGaHdPz7ZsskAOukaYg/hZkAn4rj8JJcaE/DzRy707bq6YBUpp+1ssiaadJRKR6+XMSzdyJz44Vl5rrArExrzGiNry+txRVo00U4xbIrmMX+aRKvPQ/xJ7xkxRhdxsY4F/wMcWDyJS+eyxJkHiBrHJ3ciQIDAQAB\n-----END PUBLIC KEY-----" label := "orders" plaintext := "send reinforcements, we're going to advance" ciphertext := utils.RSAEncryptOAEP(pubKey, label, plaintext) fmt.Println(ciphertext) plaintext = utils.RSADecryptOAEP(pirvatekey, label, ciphertext) fmt.Println(plaintext) ciphertext = utils.RSAEncryptPKCS1v15(pubKey, plaintext) fmt.Println(ciphertext) plaintext = utils.RSADecryptPKCS1v15(pirvatekey, ciphertext) fmt.Println(plaintext) //签名 和验证 signBytes, err := utils.SignPKCS1v15(pirvatekey, []byte(plaintext), crypto.SHA256) if err != nil { fmt.Println("SignPKCS1v15 error") } fmt.Println("SignPKCS1v15 base64:" + base64.StdEncoding.EncodeToString(signBytes)) err = utils.VerifyPKCS1v15Verify(pubKey, []byte(plaintext), signBytes, crypto.SHA256) if err == nil { fmt.Println("VerifyPKCS1v15Verify oaky") }
需要引入相应的包:
import ( "crypto" "demo/utils" "encoding/base64" "fmt" )
上面的publickey private可以 是通过utils.GenRsaKey(1024) 文件生成的,注意 -----BEGIN RSA PRIVATE KEY----- 后面有一个\n 后面结束的时候也有这个\n
windows技术爱好者
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构