由于我試圖模擬我的客戶端和我的服務器之間的連接處理資料包,我一直在努力處理位元組陣列和 BigInteger。
當我的客戶端連接到服務器時,服務器發送了一個回應,其中包含一個 RSA 公鑰,然后是一個十六進制資料包,就像這樣:
C70001A100408031313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131E5AA194C3DBA71F9A38AF85D43C130A462BDCBACF85ED702B5E2FECB47197DAA433E7B5ACF5EF09A07C5DDE79B7A2EED76B91090CB981E13DBE316997FCF5DC51BE40B2D02D912457D97924B94094227F8BC65DD61FE78060B55BEAAA31C64E3B36863B407F7183DABA9D98F0C9061DED36AD16407F70C4925951BAA8807EC95
后面的 64 位元組C70001A1004080是 RSA 公共指數。RSA 指數之后的 128 位元組是模數。
然后我嘗試提取指數和模數以重新生成 RSA 公鑰。我的步驟:
if (socket == null) socket = new Socket(loginHost, loginPort);
if (is == null) is = socket.getInputStream();
if (os == null) os = socket.getOutputStream();
int packageLength = 199;
byte[] response = IOUtils.toByteArray(is, packageLength);
byte[] rsaPubExponentBytes = Arrays.copyOfRange(response, 7, 71);
byte[] rsaModuloBytes = Arrays.copyOfRange(response, 71, packageLength);
BigInteger rsaPubExponentNumber = new BigInteger(1, rsaPubExponentBytes);
BigInteger rsaModuloNumber = new BigInteger(1, rsaModuloBytes);
PublicKey pub = null;
try {
RSAPublicKeySpec spec = new RSAPublicKeySpec(rsaModuloNumber, rsaPubExponentNumber);
KeyFactory factory = KeyFactory.getInstance("RSA");
pub = factory.generatePublic(spec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
最后我有一個公鑰:
Sun RSA public key, 1024 bits
modulus: 161275860318613570660794349609651113455378591213521007305334206887210873414776462027746458127536797075994278751416175612148660222076731030937875746805281690156725876857482174279314968596913890067397869829419019179316569148699704292044128937649866682741942026327643537075317389490824101005022833230463069842581
public exponent: 2576402308106616697565204803576809648025446765525597158856684355852417401857269811228595453373248109634555141377011045066015451991315223244608818828620081
與來自服務器的 RSA 進行比較
Sun RSA public key, 1024 bits
modulus: 105278801605955351183032861925660079240049371193037037019863031780531990060755731057393990664319512505978954889835933668032824049054190807125138251307247771506918060803959346902566451812689470408398611041302277800747341495594297701677567604614145074223483256879948522462707345079591319551080307454838134385381
public exponent: 2576402308106616697565204803576809648025446765525597158856684355852417401857269811228595453373248109634555141377011045066015451991315223244608818828620081
那么模數是錯誤的。我通過將 BigInteger 轉換為位元組陣列并用十六進制顯示它來進行雙重檢查
System.out.println(bytesToHex(rsaPubExponentNumber.toByteArray()));
System.out.println(bytesToHex(rsaModuloNumber.toByteArray()));
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("X ", b));
}
return sb.toString().replaceAll(" ", "");
}
結果是:
指數:
31313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131
模數
00E5AA194C3DBA71F9A38AF85D43C130A462BDCBACF85ED702B5E2FECB47197DAA433E7B5ACF5EF09A07C5DDE79B7A2EED76B91090CB981E13DBE316997FCF5DC51BE40B2D02D912457D97924B94094227F8BC65DD61FE78060B55BEAAA31C64E3B36863B407F7183DABA9D98F0C9061DED36AD16407F70C4925951BAA8807EC95
模數現在在開頭有 00 并且生成了公鑰,但不正確。
我也試過:
BigInteger exponent = new BigInteger(exponentHexString, 16);
BigInteger modulus = new BigInteger(modulusHexString, 16);
However, the result still the same. How can I fix this?
uj5u.com熱心網友回復:
這段代碼無法編譯。你在這里有錯誤(rsaModuloNumber 作為創建 rsaModuloNumber 的引數):
BigInteger rsaModuloNumber = new BigInteger(1, rsaModuloNumber);
并且您啟動兩個具有相同名稱的變數:
PublicKey pub = null;
和
PublicKey pub = factory.generatePublic(spec);
uj5u.com熱心網友回復:
讓我們來看看你的代碼和資料包流結構。
您將以下二進制流編碼為十六進制字串:
C70001A100408031313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131E5AA194C3DBA71F9A38AF85D43C130A462BDCBACF85ED702B5E2FECB47197DAA433E7B5ACF5EF09A07C5DDE79B7A2EED76B91090CB981E13DBE316997FCF5DC51BE40B2D02D912457D97924B94094227F8BC65DD61FE78060B55BEAAA31C64E3B36863B407F7183DABA9D98F0C9061DED36AD16407F70C4925951BAA8807EC95
根據您的代碼:
- 從索引 7 到 71 的位元組是您的指數位元組,
- 從索引 71 到流末尾的位元組是您的模數位元組。
IIUC,你想從上面的位元組串中提取指數和模數。
您面臨的問題源于這樣一個事實,即在密碼學中,數字通常是unsigned integers,具有協議定義的位元組順序,而 Java 的BigIntegers 是big-endian,有符號整數。
為了將任意整數(有符號/無符號,大端/小端)轉換為BigInteger,必須執行一些操作。
在您的情況下,按照評論中的建議,只需反轉位元組陣列就足夠了:
int packageLength = 199;
byte[] response = IOUtils.toByteArray(is, packageLength);
byte[] rsaPubExponentBytes = Arrays.copyOfRange(response, 7, 71);
byte[] rsaModuloBytes = Arrays.copyOfRange(response, 71, packageLength);
// missing step!
reverse(rsaPubExponentBytes);
reverse(rsaModuloBytes);
BigInteger rsaPubExponentNumber = new BigInteger(1, rsaPubExponentBytes);
BigInteger rsaModuloNumber = new BigInteger(1, rsaModuloBytes);
// ...
public static void reverse(byte[] arr) {
for (int i = 0; i < arr.length / 2) {
int tmp = arr[i]
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = tmp;
}
}
我在做我的一個專案時遇到了類似的問題。您可能會發現我的庫SRP-6 Variables很有幫助:
byte[] stream = new Hex("C70001A100408031313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131E5AA194C3DBA71F9A38AF85D43C130A462BDCBACF85ED702B5E2FECB47197DAA433E7B5ACF5EF09A07C5DDE79B7A2EED76B91090CB981E13DBE316997FCF5DC51BE40B2D02D912457D97924B94094227F8BC65DD61FE78060B55BEAAA31C64E3B36863B407F7183DABA9D98F0C9061DED36AD16407F70C4925951BAA8807EC95").asArray();
BigInteger exponent =
new SRP6CustomIntegerVariable(
Bytes.wrapped(Arrays.copyOfRange(stream, 7, 71)),
ByteOrder.LITTLE_ENDIAN
).asNonNegativeBigInteger();
BigInteger modulus =
new SRP6CustomIntegerVariable(
Bytes.wrapped(Arrays.copyOfRange(stream, 71, stream.length)),
ByteOrder.LITTLE_ENDIAN
).asNonNegativeBigInteger();
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/370124.html
標籤:java arrays rsa biginteger
下一篇:獲取for回圈中數字的總和
