2017-04-10 153 views
1

目前,我正在研究一些套接字的東西來建立一個簡單的加密聊天。服務器用Go編寫,客戶端用Java編寫。 我的服務器&客戶端已經在工作並可以通信。我的下一個目標是加密客戶端&服務器之間的流量。爲什麼我的服務器(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 

再次,這是我檢查,什麼是好的:

  • 鍵轉換爲字符串&提交給客戶
  • 重點從字符串轉換到AsymmetricKeyParameter
  • 編碼
  • 加密/解密工作在一個網站上(客戶端< - >客戶端&服務器< - >服務器

總之什麼不工作:

  • 來自客戶端的解密字符串

也許我沒有看到一個很小的錯誤,或者完全忘記了一些事情。我認爲他們是一些聰明的人,可以告訴我什麼是錯,或給我一個提示。如果您需要更多代碼示例或其他信息,請隨時提問。

編輯:我檢查了加密的字符串,以確保服務器收到客戶端發送的相同字符串。這裏都是加密的字符串:

客戶:

GnUapW7dxa3zXwVzNAVOJs6lcfeb6Nv0OKDM8QvPMb9jqozsGYdlET09D2Nc9F7bMfVbBMeLujlxwu8NqbvYABpoYd7uwRZJfEh/VexIEbsdkVxQUr+PEvBlE/ekkSJIV9ymCVllmRForvq7WU3pva9e56owp1NdVJGFVYVKbp8=

服務器:

GnUapW7dxa3zXwVzNAVOJs6lcfeb6Nv0OKDM8QvPMb9jqozsGYdlET09D2Nc9F7bMfVbBMeLujlxwu8NqbvYABpoYd7uwRZJfEh/VexIEbsdkVxQUr+PEvBlE/ekkSJIV9ymCVllmRForvq7WU3pva9e56owp1NdVJGFVYVKbp8=

在我看來,他們看起來一樣的,所以這不應該成爲問題。此外,客戶端和服務器都使用OAEP和SHA256。

非常感謝大家的幫助!

+0

PS:我已經搜查谷歌的解決方案,沒有什麼工作。再次小信息:服務器代碼用Go(Golang)編寫,客戶端代碼用Java編寫。 – Max

+0

當你說密鑰是作爲UTF8編碼字符串發送的時候,你的意思是你正在編碼UTF8的原始DER格式公鑰併發送它? –

+0

@LukePark不,我實際上想說我正在向客戶端發送Base64解碼字符串。我會在我的帖子中解決這個問題。 – Max

回答

0

解決: 我想到了一個自己編寫的安全算法已爲這個項目帶來的好處,並得出結論認爲默認TLS就足夠了這一點。 TLS非常容易與Go & Java一起使用,因此我將使用TLS構建此聊天應用程序。

這裏是一個很好的例子如何實現TLS服務器端圍棋: Simple Golang HTTPS/TLS Examples

這裏是我的客戶如何能利用TLS和網絡插口的一些信息:How to use a SSL WebSocket client

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("Decryption error: ", err) 
     return "" 
    } else { 
     return string(sDecrypted[:]) 
    } 
} 
+0

我會稍後再試。謝謝。 – Max

+0

好吧,它仍然不起作用......我讓兩個程序都打印出加密的消息,以確保服務器準確接收客戶端發送的內容,這看起來很好。我會在上面的問題中列舉一個例子。 – Max

相關問題