如何将C#的RijndaelManaged加密函数重写为Go实现并输出一致
问题排查与修复方案
核心错误点
- 错误1:加密算法不匹配
C#代码显式设置BlockSize = 256,使用的是256位块大小的Rijndael算法,而Go标准库crypto/aes仅支持128位块大小的AES标准(AES是Rijndael的子集,仅支持128位块),两者算法实现基础不一致。 - 错误2:IV逻辑不符合C#实现
当前Go代码每次从随机数生成IV,还将IV拼接在密文前返回,这是导致每次输出结果不同的直接原因。C#侧使用固定全局IV,且不会将IV附加到输出密文中。 - 错误3:填充块大小错误
当前代码使用aes.BlockSize(16字节)作为PKCS7填充的块大小,C#侧使用256位(32字节)块大小做填充,两者填充结果不一致。
修复步骤
- 首先安装支持可变块大小的Rijndael依赖:
go get golang.org/x/crypto/rijndael
- 替换修改Go代码如下:
package main import ( "bytes" "crypto/cipher" "encoding/base64" "errors" "fmt" "golang.org/x/crypto/rijndael" ) var KEY = []byte("095fc90fe8b18e8f243e4b07a9c0d170") var IV = []byte("8bef55a546d27958ead1fdddba4d36ea") const RIJNDAEL_BLOCK_SIZE = 32 // 对应C#侧256位块大小 func encrypt(myInput string) []byte { plaintext := []byte(myInput) // 初始化256位密钥、256位块的Rijndael算法 block, err := rijndael.NewCipher(KEY) if err != nil { panic(err) } // 按32字节块大小做PKCS7填充 plaintext, err = pkcs7Pad(plaintext, RIJNDAEL_BLOCK_SIZE) if err != nil { panic(err) } // 直接使用全局固定IV,不随机生成、不拼接到密文前 ciphertext := make([]byte, len(plaintext)) bm := cipher.NewCBCEncrypter(block, IV) bm.CryptBlocks(ciphertext, plaintext) return ciphertext } // pkcs7Pad 保持原有逻辑不变 func pkcs7Pad(b []byte, blocksize int) ([]byte, error) { if blocksize <= 0 { return nil, errors.New("invalid blocksize") } if b == nil || len(b) == 0 { return nil, errors.New("invalid PKCS7 data (empty or not padded)") } n := blocksize - (len(b) % blocksize) pb := make([]byte, len(b)+n) copy(pb, b) copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n)) return pb, nil } func main() { plainText := "{\"randJsonList\":[ \"abc\" ], \"name\":\"baron\", \"support\":\"king\"}" x := encrypt(plainText) outputString := base64.StdEncoding.EncodeToString(x) fmt.Println(outputString) // 输出结果与C#一致:DdSUyoYRYW/zDNSVaA1JZ39WqJt06qp0FiJUlCW5BbZWEt41GzsmtgVnGZuHigZNs7qKhI+kHAKMXL8EPnK1vg== }
内容的提问来源于stack exchange,提问作者arizona525
相关产品推荐
相关产品推荐

