为什么我的服务器(Go)无法解密客户端(Java)的消息?

huangapple go评论69阅读模式
英文:

Why is my server (Go) unable to decrypt the clients (Java) message?

问题

目前,我正在处理一些套接字相关的工作,以构建一个带有加密功能的简单聊天应用。服务器端使用Go语言编写,客户端使用Java语言编写。
我的服务器和客户端已经可以正常通信。我的下一个目标是加密客户端和服务器之间的通信。

我想使用RSA和AES来加密在两个目标之间传输的所有数据。当客户端连接时,服务器将向客户端发送其公钥,客户端将使用该公钥加密其AES密钥并将其发送回服务器。

现在的主要问题是,我无法解密客户端发送回服务器的数据。我已经比较了加密数据,并尝试了一下我的加密/解密方法是否能正常工作。它们确实可以正常工作。但是一旦涉及到客户端使用公钥加密,服务器使用私钥解密的过程,就无法正常工作。

以下是生成新的RSA密钥对的服务器代码:

func GenerateKeyPair() RSAKeyPair {
    log.Println("Generating RSA keys. This could take a while.")

    startTime := time.Now()

    privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
    if err != nil {
        log.Fatal("Couldn't generate RSA keys. Message: ", err)
        os.Exit(1)
    }

    var publicKey *rsa.PublicKey
    publicKey = &privateKey.PublicKey

    elapsedTime := time.Since(startTime)
    log.Printf("RSA keys ready after %s.", elapsedTime)

    return RSAKeyPair{Private: *privateKey, Public: *publicKey}
}

这是表示RSA密钥对的结构体:

type RSAKeyPair struct {
    Private rsa.PrivateKey
    Public  rsa.PublicKey
}

这是服务器端解密字符串的函数:

func DecryptStringRSA(s string, key rsa.PrivateKey) string {
    b64Bytes, _ := base64.StdEncoding.DecodeString(s)
    sDecrypted, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &key, []byte(s), nil)
    if err != nil {
        log.Println("Decryption error: ", err)
        return ""
    } else {
        return string(sDecrypted[:])
    }
}

我在客户端使用了Bouncy Castle。服务器将公钥作为Base64解码的字符串发送(现在它是可读的),客户端将该字符串转换为AsymmetricKeyParameter。这个转换也是正常工作的,我已经检查过了。

客户端加密字符串的方法:

public String encryptString(String string, AsymmetricKeyParameter publicKey) throws UnsupportedEncodingException, InvalidCipherTextException {
    Security.addProvider(new BouncyCastleProvider());
    RSAEngine rsaEngine = new RSAEngine();
    AsymmetricBlockCipher blockCipher = new OAEPEncoding(rsaEngine, new SHA256Digest(), new SHA256Digest(), null);
    blockCipher.init(true, publicKey);

    byte[] bytes = string.getBytes("UTF-8");
    byte[] encryptedBytes = blockCipher.processBlock(bytes, 0, bytes.length);
    return Base64.getEncoder().encodeToString(encryptedBytes);
}

在客户端加密一个字符串并将其发送回服务器后,服务器应该解密它并继续执行其预定的操作,但实际上,它只给出了以下错误:

crypto/rsa: decryption error

再次强调,这是我检查过的并且没有问题的部分:

  • 密钥转换为字符串并发送给客户端
  • 字符串到AsymmetricKeyParameter的转换
  • 编码
  • 加密/解密在一个方向上正常工作(客户端 <-> 客户端和服务器 <-> 服务器)

简而言之,不起作用的是:

  • 解密来自客户端的字符串

也许我没有注意到一个非常小的错误,或者完全忘记了某些事情。我认为有一些聪明的人可以告诉我出了什么问题,或者给我一些提示。如果你需要更多的代码示例或其他信息,请随时提问。

编辑:我检查了加密的字符串,以确保服务器接收到的字符串与客户端发送的字符串相同。以下是两个加密字符串:

客户端:

GnUapW7dxa3zXwVzNAVOJs6lcfeb6Nv0OKDM8QvPMb9jqozsGYdlET09D2Nc9F7bMfVbBMeLujlxwu8NqbvYABpoYd7uwRZJfEh/VexIEbsdkVxQUr+PEvBlE/ekkSJIV9ymCVllmRForvq7WU3pva9e56owp1NdVJGFVYVKbp8=

服务器:

GnUapW7dxa3zXwVzNAVOJs6lcfeb6Nv0OKDM8QvPMb9jqozsGYdlET09D2Nc9F7bMfVbBMeLujlxwu8NqbvYABpoYd7uwRZJfEh/VexIEbsdkVxQUr+PEvBlE/ekkSJIV9ymCVllmRForvq7WU3pva9e56owp1NdVJGFVYVKbp8=

在我看来,它们看起来是相同的,所以这不应该是问题。而且客户端和服务器都使用了带有SHA256的OAEP。

非常感谢大家提前的帮助!

英文:

Currently, I am working on some socket stuff to build a simple chat with encryption. The server is written in Go and the client is written in Java.
My server & client are already working and can communicate. My next goal is to encrypt the traffic between client & server.

I want to use RSA and AES to encrypt all data that will be transferred between both targets. When a client connects, the server will send his public RSA key to the client which will encrypt his AES key and send it back to the server.

The main problem is now, that I can't decrypt what the client sends back to the server. I already compared the encrypted data and tried if my encryption/decryption methods work in general. And they do. But as soon as it comes to the point where the client encrypts with a public key and the server has to decrypt it with its private key it won't work.

Here is the server code that generates a new RSA key pair:

func GenerateKeyPair() RSAKeyPair {
	log.Println(&quot;Generating RSA keys. This could take a while.&quot;)

	startTime := time.Now()

	privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
		log.Fatal(&quot;Couldn&#39;t generate RSA keys. Message: &quot;, err)
		os.Exit(1)
	}

	var publicKey *rsa.PublicKey
	publicKey = &amp;privateKey.PublicKey

	elapsedTime := time.Since(startTime)
	log.Printf(&quot;RSA keys ready afert %s.&quot;, elapsedTime)

	return RSAKeyPair{Private: *privateKey, Public: *publicKey}
}

This is the struct that represents the RSAKeyPair

type RSAKeyPair struct {
	Private rsa.PrivateKey
	Public  rsa.PublicKey
}

This is the server-side function to decrypt a string:

func DecryptStringRSA(s string, key rsa.PrivateKey) string {
	b64Bytes, _ := base64.StdEncoding.DecodeString(s)
	sDecrypted, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &amp;key, []byte(s), nil)
	if err != nil {
		log.Println(&quot;Decryption error: &quot;, err)
		return &quot;&quot;
	} else {
		return string(sDecrypted[:])
	}
}

I am using Bouncy Castle on the client side. The server sends the public key as Base64 decoded string (it's human readable now) and the client converts the string into an AsymmetricKeyParameter. This conversion also works fine, I checked that.

The client's method to encrypt a string:

public String encryptString(String string, AsymmetricKeyParameter publicKey) throws UnsupportedEncodingException, InvalidCipherTextException {
        Security.addProvider(new BouncyCastleProvider());
        RSAEngine rsaEngine = new RSAEngine();
        AsymmetricBlockCipher blockCipher = new OAEPEncoding(rsaEngine, new SHA256Digest(), new SHA256Digest(), null);
        blockCipher.init(true, publicKey);

        byte[] bytes = string.getBytes(&quot;UTF-8&quot;);
        byte[] encryptedBytes = blockCipher.processBlock(bytes, 0, bytes.length);
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

After the client encrypted a string and sent it back to the server, the server should decrypt it and continue doing what he is supposed to do but instead, it just gives me following error:

crypto/rsa: decryption error

Again this is what I checked and what is ok:

  • Key conversion to string & submitting to client
  • Key conversion from string to AsymmetricKeyParameter
  • Encodings
  • Encryption/Decryption works on one site (Client <-> Client & Server <-> Server

In short what is not working:

  • Decrypt string which came from client

Maybe I didn't see a really small mistake or just completely forgot about something. I think there are some smart people that out there that can tell me what is wrong or give me a hint. If you need more code examples or additional information feel free to ask.

Edit: I checked the the encrypted string to make sure the serve receives the same string the client is sending. Here are both encrypted strings:

Client:
> GnUapW7dxa3zXwVzNAVOJs6lcfeb6Nv0OKDM8QvPMb9jqozsGYdlET09D2Nc9F7bMfVbBMeLujlxwu8NqbvYABpoYd7uwRZJfEh/VexIEbsdkVxQUr+PEvBlE/ekkSJIV9ymCVllmRForvq7WU3pva9e56owp1NdVJGFVYVKbp8=

Server:
> GnUapW7dxa3zXwVzNAVOJs6lcfeb6Nv0OKDM8QvPMb9jqozsGYdlET09D2Nc9F7bMfVbBMeLujlxwu8NqbvYABpoYd7uwRZJfEh/VexIEbsdkVxQUr+PEvBlE/ekkSJIV9ymCVllmRForvq7WU3pva9e56owp1NdVJGFVYVKbp8=

In my opinion they look the same so this shouldn't be the problem. Also client and server are both using OAEP with SHA256.

Thank you all in advance for your help!

答案1

得分: 1

你正在解密 base64 编码的字符串 's',而不是 'b64Bytes'。不过你的代码无法编译,所以可能这不是实际的代码?这里是一个可以编译的解决方案:

func DecryptStringRSA(s string, key rsa.PrivateKey) string {
    b64Bytes, _ := base64.StdEncoding.DecodeString(s)
    sDecrypted, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &key, b64Bytes, nil)
    if err != nil {
        log.Println("解密错误:", err)
        return ""
    } else {
        return string(sDecrypted[:])
    }
}

请注意,这只是一个编译通过的解决方案,具体是否符合你的需求还需要进一步确认。

英文:

You are decrypting the base64 encoded string 's', instead of 'b64Bytes'. Your code is not compiling though, so maybe this is not the actual code? Here is a compiling solution:

func DecryptStringRSA(s string, key rsa.PrivateKey) string {
    b64Bytes, _ := base64.StdEncoding.DecodeString(s)
    sDecrypted, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &amp;key, b64Bytes, nil)
    if err != nil {
        log.Println(&quot;Decryption error: &quot;, err)
        return &quot;&quot;
    } else {
        return string(sDecrypted[:])
    }
}

答案2

得分: 0

已解决:
我考虑了自己编写安全算法对这个项目的好处,并得出结论,对于这个项目来说,默认的TLS就足够了。TLS在Go和Java中使用起来非常简单,所以我将使用TLS构建这个聊天应用程序。

这里有一个很好的例子,展示了如何在Go中实现服务器端的TLS:
简单的Golang HTTPS/TLS示例

这里有一些关于我的客户端如何使用TLS和WebSockets的信息:如何使用SSL WebSocket客户端

英文:

SOLVED:
I thought about the benefits a self-written security algorithm has for this project and came to the conclusion that default TLS would be enough for this. TLS is pretty easy to use with Go & Java so I will build up this chat application with TLS.

Here is a nice example how to implement TLS server side in Go:
Simple Golang HTTPS/TLS Examples

Here is some information of how my client could make use of TLS and web sockets: How to use a SSL WebSocket client

huangapple
  • 本文由 发表于 2017年4月11日 02:36:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/43330545.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定