【发布时间】:2017-04-10 18:36:34
【问题描述】:
目前,我正在研究一些套接字的东西来建立一个简单的加密聊天。服务器是用 Go 编写的,客户端是用 Java 编写的。 我的服务器和客户端已经在工作并且可以通信了。我的下一个目标是加密客户端和服务器之间的流量。
我想使用 RSA 和 AES 加密将在两个目标之间传输的所有数据。当客户端连接时,服务器会将他的公共 RSA 密钥发送给客户端,客户端将加密他的 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 afert %s.", elapsedTime)
return RSAKeyPair{Private: *privateKey, Public: *publicKey}
}
这是表示 RSAKeyPair 的结构
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
这也是我检查过的,没问题:
- 密钥转换为字符串并提交给客户端
- 从字符串到非对称密钥参数的密钥转换
- 编码
- 加密/解密在一个站点上工作(客户端 客户端和服务器 服务器
简而言之,什么不起作用:
- 解密来自客户端的字符串
也许我没有看到一个非常小的错误,或者只是完全忘记了某些事情。我认为有一些聪明的人可以告诉我哪里出了问题或给我提示。如果您需要更多代码示例或其他信息,请随时询问。
编辑:我检查了加密字符串以确保服务器接收到客户端发送的相同字符串。以下是两个加密字符串:
客户:
GnUapW7dxa3zXwVzNAVOJs6lcfeb6Nv0OKDM8QvPMb9jqozsGYdlET09D2Nc9F7bMfVbBMeLujlxwu8NqbvYABpoYd7uwRZJfEh/VexIEbsdkVxQUr+PEvBlE/ekkSJIV9ymCVllmRForvq7pWU3pVeK6Vpwq7WU3pVa
服务器:
GnUapW7dxa3zXwVzNAVOJs6lcfeb6Nv0OKDM8QvPMb9jqozsGYdlET09D2Nc9F7bMfVbBMeLujlxwu8NqbvYABpoYd7uwRZJfEh/VexIEbsdkVxQUr+PEvBlE/ekkSJIV9ymCVllmRForvq7pWU3pVeK6Vpwq7WU3pVa
在我看来,它们看起来一样,所以这不应该是问题。客户端和服务器都使用 SHA256 的 OAEP。
提前感谢大家的帮助!
【问题讨论】:
-
PS:我已经在 Google 上搜索过解决方案,但没有任何效果。小信息:服务器代码是用 Go (Golang) 编写的,客户端代码是用 Java 编写的。
-
当您说密钥作为 UTF8 编码字符串发送时,您的意思是您将原始 DER 格式的公钥编码为 UTF8 并发送吗?
-
我目前无法检查代码,但是您所描述的对于聊天应用程序来说并不好。它很容易受到中间人的攻击。客户端也需要向服务器进行身份验证。你需要制定一个协议并检查它是否存在潜在的攻击。
-
@jackgu1988 我认为 OP 说这只是一个个人项目。对于 OP,如果不是这种情况,我同意 jackgu1988,您的系统存在缺陷,实际上并不安全。我敢说打破它是微不足道的。
-
@jackgu1988 是的,我知道这个问题。这将是我清单上的下一点。不过还是谢谢你的提示。
标签: java security encryption go cryptography