简体   繁体   English

错误RSA在C#加密,在Go解密

[英]Error RSA encrypting in C# and decrypting in Go

I am getting an error decrypting a message in go that was encrypted in C# (using corresponding public/private keys)我在解密 go 中的一条消息时出错,该消息在 C# 中加密(使用相应的公钥/私钥)

My client is written in C# and my server is written in Go. I generated a private and public key via go's crypto/rsa package (using rsa.GenerateKey(random Reader, bits int) ).我的客户端写在 C# 中,我的服务器写在 Go 中。我通过 go 的 crypto/rsa package(使用rsa.GenerateKey(random Reader, bits int) )生成了私钥和公钥。 I then store the public key file generated where the client can access it and the private key where the server can access it.然后,我将生成的公钥文件存储在客户端可以访问的位置,并将私钥存储在服务器可以访问的位置。 I encrypt on the client with the following code (using bouncy castle):我使用以下代码在客户端加密(使用充气城堡):

   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());
}

The go server parses this string from the header and uses the private key to decrypt: 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
}

The decryption function throws crypto/rsa: decryption error .解密 function 抛出crypto/rsa: decryption error If I try pasting the cipher text directly into go (rather then sending from the client), the same error occurs.如果我尝试将密文直接粘贴到 go(而不是从客户端发送),则会发生同样的错误。

NOTE: in order to get the public key to load, I needed to change the header from:注意:为了加载公钥,我需要将 header 从:

-----BEGIN RSA PUBLIC KEY----- 
...

to

-----BEGIN PUBLIC KEY----- 
...

and the same for the footer.页脚也一样。 I am assuming this is a formatting issue but not sure how to go about solving.我假设这是一个格式问题,但不确定如何解决 go。

EDIT: it seems that golang OAEP uses sha256 and bouncy castle uses SHA-1.编辑:似乎 golang OAEP 使用 sha256 而 bouncy castle 使用 SHA-1。 Go's documentation specifies that the hash for encryption and decryption must be the same. Go的文档规定加密和解密的hash必须相同。 This seems likely to be the issue?这似乎是问题所在? If it is, how can I change the hashing algorithm used by either go or C#?如果是,我如何更改 go 或 C# 使用的哈希算法?

Yes, you need to match the hash. In GoLang you've already set it to SHA-512 if I take a look at your code.是的,您需要匹配 hash。如果我看一下您的代码,在 GoLang 中您已经将其设置为 SHA-512。 Using SHA-256 at minimum should probably be preferred, but using SHA-1 is relatively safe as the MGF1 function doesn't rely on the collision resistance of the underlying hash. It's also the default for most runtimes, I don't know why GoLang decided against that.至少应该首选使用 SHA-256,但使用 SHA-1 相对安全,因为 MGF1 function 不依赖底层 hash 的抗碰撞性。这也是大多数运行时的默认设置,我不知道为什么GoLang 决定反对。

Probably the best is to set SHA-512 for both runtimes, so here is the necessary constant for .NET.可能最好的方法是为两个运行时设置 SHA-512,因此是 .NET 的必要常量。


Note that the underlying story is even more complex as OAEP uses a hash over a label as well as a hash within MGF1 (mask generation function 1, the only one specified).请注意,由于 OAEP 使用 hash 而不是 label 以及 MGF1 中的 hash(掩码生成 function 1,唯一指定的),因此底层故事更加复杂。 Both need to be specified in advance and generally the same hash function is used, but sometimes it is not .两者都需要提前指定,一般使用相同的hash function,但有时也不是

The label is generally empty and most runtimes don't even allow setting it, so the hash value over the label is basically a hash-function specific constant that doesn't matter for security. label 通常为空,大多数运行时甚至不允许设置它,因此 label 上的 hash 值基本上是哈希函数特定常量,与安全性无关。 The constant just manages to make things incompatible;常量只是设法使事情不兼容; "More flexible" isn't always a good thing. “更灵活”并不总是一件好事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM