在 C# 中加密和在 Go 中解密的错误 RSA
Error RSA encrypting in C# and decrypting in Go
我在解密一条用 C# 加密的消息时出错(使用相应的 public/private 密钥)
我的客户端是用C#写的,我的服务器是用Go写的。我通过 go 的 crypto/rsa 包(使用 rsa.GenerateKey(random Reader, bits int)
)生成了一个私钥和 public 密钥。然后,我将生成的 public 密钥文件存储在客户端可以访问的位置,并将私钥存储在服务器可以访问的位置。我使用以下代码在客户端加密(使用充气城堡):
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PemReader pr = new PemReader(
new StringReader(m_publicKey)
);
RsaKeyParameters keys = (RsaKeyParameters)pr.ReadObject();
// PKCS1 OAEP paddings
OaepEncoding eng = new OaepEncoding(new RsaEngine());
eng.Init(true, keys);
int length = plainTextBytes.Length;
int blockSize = eng.GetInputBlockSize();
List<byte> cipherTextBytes = new List<byte>();
for (int chunkPosition = 0; chunkPosition < length; chunkPosition += blockSize)
{
int chunkSize = Math.Min(blockSize, length - chunkPosition);
cipherTextBytes.AddRange(eng.ProcessBlock(
plainTextBytes, chunkPosition, chunkSize
));
}
return Convert.ToBase64String(cipherTextBytes.ToArray());
}
go服务器从header解析出这个字符串,并使用私钥解密:
func DecryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) []byte {
hash := sha512.New()
plaintext, err := rsa.DecryptOAEP(hash, rand.Reader, priv, ciphertext, nil)
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
}
return plaintext
}
解密函数抛出crypto/rsa: decryption error
。如果我尝试将密文直接粘贴到 go 中(而不是从客户端发送),也会出现同样的错误。
注意:为了加载 public 密钥,我需要将 header 更改为:
-----BEGIN RSA PUBLIC KEY-----
...
到
-----BEGIN PUBLIC KEY-----
...
页脚也一样。我假设这是一个格式问题,但不确定如何解决。
编辑:golang OAEP 似乎使用 sha256 而 bouncy castle 使用 SHA-1。 Go的文档规定加密和解密的hash必须相同。这似乎是问题所在?如果是,我如何更改 go 或 C# 使用的哈希算法?
是的,您需要匹配哈希。在 GoLang 中,如果我查看您的代码,您已经将其设置为 SHA-512。至少应该首选使用 SHA-256,但使用 SHA-1 相对安全,因为 MGF1 函数不依赖于底层哈希的抗碰撞性。它也是大多数运行时的默认设置,我不知道为什么 GoLang 决定反对它。
可能最好的方法是为两个运行时设置 SHA-512,因此 here 是 .NET 的必要常量。
请注意,由于 OAEP 在标签上使用散列以及 MGF1 中的散列(掩码生成函数 1,唯一指定的),因此底层故事更加复杂。两者都需要提前指定,一般使用相同的哈希函数,但是sometimes it is not.
标签通常是空的,大多数运行时甚至不允许设置它,因此标签上的散列值基本上是一个与安全性无关的散列函数特定常量。常量只是设法使事情不兼容; “更灵活”并不总是一件好事。
我在解密一条用 C# 加密的消息时出错(使用相应的 public/private 密钥)
我的客户端是用C#写的,我的服务器是用Go写的。我通过 go 的 crypto/rsa 包(使用 rsa.GenerateKey(random Reader, bits int)
)生成了一个私钥和 public 密钥。然后,我将生成的 public 密钥文件存储在客户端可以访问的位置,并将私钥存储在服务器可以访问的位置。我使用以下代码在客户端加密(使用充气城堡):
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PemReader pr = new PemReader(
new StringReader(m_publicKey)
);
RsaKeyParameters keys = (RsaKeyParameters)pr.ReadObject();
// PKCS1 OAEP paddings
OaepEncoding eng = new OaepEncoding(new RsaEngine());
eng.Init(true, keys);
int length = plainTextBytes.Length;
int blockSize = eng.GetInputBlockSize();
List<byte> cipherTextBytes = new List<byte>();
for (int chunkPosition = 0; chunkPosition < length; chunkPosition += blockSize)
{
int chunkSize = Math.Min(blockSize, length - chunkPosition);
cipherTextBytes.AddRange(eng.ProcessBlock(
plainTextBytes, chunkPosition, chunkSize
));
}
return Convert.ToBase64String(cipherTextBytes.ToArray());
}
go服务器从header解析出这个字符串,并使用私钥解密:
func DecryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) []byte {
hash := sha512.New()
plaintext, err := rsa.DecryptOAEP(hash, rand.Reader, priv, ciphertext, nil)
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
}
return plaintext
}
解密函数抛出crypto/rsa: decryption error
。如果我尝试将密文直接粘贴到 go 中(而不是从客户端发送),也会出现同样的错误。
注意:为了加载 public 密钥,我需要将 header 更改为:
-----BEGIN RSA PUBLIC KEY-----
...
到
-----BEGIN PUBLIC KEY-----
...
页脚也一样。我假设这是一个格式问题,但不确定如何解决。
编辑:golang OAEP 似乎使用 sha256 而 bouncy castle 使用 SHA-1。 Go的文档规定加密和解密的hash必须相同。这似乎是问题所在?如果是,我如何更改 go 或 C# 使用的哈希算法?
是的,您需要匹配哈希。在 GoLang 中,如果我查看您的代码,您已经将其设置为 SHA-512。至少应该首选使用 SHA-256,但使用 SHA-1 相对安全,因为 MGF1 函数不依赖于底层哈希的抗碰撞性。它也是大多数运行时的默认设置,我不知道为什么 GoLang 决定反对它。
可能最好的方法是为两个运行时设置 SHA-512,因此 here 是 .NET 的必要常量。
请注意,由于 OAEP 在标签上使用散列以及 MGF1 中的散列(掩码生成函数 1,唯一指定的),因此底层故事更加复杂。两者都需要提前指定,一般使用相同的哈希函数,但是sometimes it is not.
标签通常是空的,大多数运行时甚至不允许设置它,因此标签上的散列值基本上是一个与安全性无关的散列函数特定常量。常量只是设法使事情不兼容; “更灵活”并不总是一件好事。