我試圖通過Java中的套接字連接發送公鑰。雖然我非常清楚Java爲這類活動提供了SSL功能,但這是一項單獨的任務;我無法使用Java實現。Java:通過套接字發送後的公鑰不同
服務器對其公鑰進行編碼並通過套接字連接將其發送給客戶端。當客戶端收到密鑰並對其進行解碼時,它看起來不同。不僅如此,客戶端接收到的數據與服務器發送的數據不同。我相信當我嘗試使用此密鑰對用戶名和密碼進行加密時,會給我帶來問題。
客戶:
public class TestClient {
/**
* @param args
*/
public static void main(String[] args) {
final int sPort = 4321;
Socket sock = null;
Key serverPubKey = null;
BufferedReader clientIn = null;
// Initialise server connection
try{
sock = new Socket(InetAddress.getLocalHost(), sPort);
clientIn = new BufferedReader(new InputStreamReader(sock.getInputStream()));
} catch (UnknownHostException e) {
System.out.println("Unknown host.");
System.exit(1);
} catch (IOException e) {
System.out.println("No I/O");
System.exit(1);
}
// Get server pub key
try{
int len = Integer.parseInt(clientIn.readLine());
byte[] servPubKeyBytes = new byte[len];
sock.getInputStream().read(servPubKeyBytes,0,len);
System.out.println(servPubKeyBytes);
X509EncodedKeySpec ks = new X509EncodedKeySpec(servPubKeyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
serverPubKey = kf.generatePublic(ks);
System.out.println(serverPubKey.getEncoded());
} catch (IOException e) {
System.out.println("Error obtaining server public key 1.");
System.exit(0);
} catch (NoSuchAlgorithmException e) {
System.out.println("Error obtaining server public key 2.");
System.exit(0);
} catch (InvalidKeySpecException e) {
System.out.println("Error obtaining server public key 3.");
System.exit(0);
}
}
}
服務器:
public class TestServer {
public static void main(String[] args) {
final int servPort = 4321;
final int RSAKeySize = 1024;
final String newline = "\n";
Key pubKey = null;
ServerSocket cServer = null;
Socket cClient = null;
PrintWriter cOut = null;
// Initialise RSA
try{
KeyPairGenerator RSAKeyGen = KeyPairGenerator.getInstance("RSA");
RSAKeyGen.initialize(RSAKeySize);
KeyPair pair = RSAKeyGen.generateKeyPair();
pubKey = pair.getPublic();
} catch (GeneralSecurityException e) {
System.out.println(e.getLocalizedMessage() + newline);
System.out.println("Error initialising encryption. Exiting.\n");
System.exit(0);
}
// Initialise socket connection
try{
cServer = new ServerSocket(servPort);
cClient = cServer.accept();
cOut = new PrintWriter(cClient.getOutputStream(), true);
} catch (IOException e) {
System.out.println("Error initialising I/O.\n");
System.exit(0);
}
// Send public key
try {
cOut.println(pubKey.getEncoded().length);
System.out.println(pubKey.getEncoded());
cClient.getOutputStream().write(pubKey.getEncoded());
cClient.getOutputStream().flush();
} catch (IOException e) {
System.out.println("I/O Error");
System.exit(0);
}
}
}
這可能是由於通知我我的鑰匙一樣簡單不X509編碼
這個問題可以用下面的代碼進行復制,但是這似乎是從文件中恢復密鑰(也讀爲字節)的方式,所以我不明白爲什麼它不起作用?
非常感謝您的幫助/建議。
編輯:問題已解決,請參閱Jeffrey的回覆。修改後的(工作)代碼作爲響應發佈。
爲什麼你的代碼有像「系統語句。通過out.println(pubKey.getEncoded())「? PrintStream.println對byte []沒有做任何特殊的處理,所以只會打印出類似於「[B @ 10b62c9」(意思是在內存位置0x010B62C9處的一個字節[])。我問,因爲你說「客戶收到的數據看起來與服務器傳輸的數據不同」,我希望上面的陳述不是你如何確定的。 – ruakh
@ruakh「,我希望上面的陳述不是你如何確定的」不幸的是,這正是我所做的。我幾乎是一個java處女,實際上,我認爲它正在做一些不可思議的類型轉換爲char數組或字符串,「new String(pubKey.getEncoded())」會幫助我確定發送/接收的數據是否一樣?據我所知,字節數組可能無法正確編碼,但如果它們相等,我至少可以大致假設是這種情況,並嘗試再次加密我的用戶/密碼。 – mkingston
我建議使用「System.out.println(javax.xml.bind.DatatypeConverter.printHexBinary(pubKey.getEncoded()))」,它使用JDK 1.6 DatatypeConverter類(hat-tip來Sii)轉換每個字節分成兩個十六進制數字。否則,您將打印字節到您的控制檯,而不是ASCII打印字符 - 難以比較,並且如果警報/響鈴/嘟嘟聲字符在您的耳朵上,您的耳朵會很難受! – ruakh