Исключение InvalidKeySpecException в Java

У меня есть клиент (приложение Android с Java) и сервер Node.js. Я хочу сгенерировать общий секрет, используя открытые ключи Диффи-Хеллмана клиента и сервера.

Сервер и клиент отправляют свои открытые ключи Диффи-Хеллмана друг другу через TCP (протокол управления передачей), чтобы они могли сгенерировать общий секрет. Когда сервер отправляет свой открытый ключ клиенту в виде строки base64, я могу успешно преобразовать эту строку в байты на стороне клиента.

Проблема в том, что при преобразовании байтов в экземпляр PublicKey в отмеченной строке 9 я получаю ошибку:

java.security.spec.InvalidKeySpecException: спецификация закодированного ключа не распознана: не удалось создать последовательность из byte[]: длина DER более 4 байтов: 33

Вот мой Java-код:

public boolean generateSharedSecret() throws Exception {
        byte[] serverDiffieHellmanPublicKey = receiveDiffieHellmanPublicKey();

        Log.e("String Length", String.valueOf(Base64.encodeToString(serverDiffieHellmanPublicKey, Base64.DEFAULT).length())); // Outputs 90.
        Log.e("Bytes Length", String.valueOf(serverDiffieHellmanPublicKey.length)); // Outputs 64.

        KeyFactory keyFactory = KeyFactory.getInstance("DH");
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(serverDiffieHellmanPublicKey);
        PublicKey dhPublicKeyFromServer = keyFactory.generatePublic(x509EncodedKeySpec); // Line 9

        // ...
}

public byte[] receiveDiffieHellmanPublicKey() {
    try {
        Socket socket = new Socket("185.255.95.248", 1211);
        InputStream inputStream = socket.getInputStream();
        byte[] buffer = new byte[1024];
        int bytesRead = inputStream.read(buffer);
        String keyString = new String(buffer, 0, bytesRead);
        return Base64.decode(keyString, Base64.DEFAULT);
    } catch (Exception ignore) {}
}

generateSharedSecret();

Вот мой код Node.js:

const net = require("net");
const crypto = require("crypto");
const dh = crypto.createDiffieHellman(512);
const serverDiffieHellman = crypto.generateDiffieHellman(dh.getPrime());

net.createServer((socket) => {
    socket.on("connect", () => socket.write(serverDiffieHellman.getPublicKey().toString("base64"));
}).listen(1211, "185.255.95.248", () => console.info("TCP server is running..."));

Любая помощь будет приятно оценена. С уважением...

Первая ошибка — использовать inputStream.read(buffer); и ожидать, что он прочитает все данные. Если вы хотите передать данные, сначала отправьте длину данных, чтобы получатель знал, сколько байтов нужно прочитать и использовать. Что касается формата ключа, я бы рекомендовал посмотреть его структуру ASN.1 в этом средстве просмотра: lapo.it/asn1js Затем сравните его с форматом, указанным в docs.oracle.com/javase/8/docs/api. /java/security/spec/…

Robert 31.07.2024 14:22

@Роберт, спасибо. Я смог решить проблему. Вы можете посмотреть мой ответ...

user26341567 01.08.2024 15:19
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В конечном итоге мне удалось полностью решить проблему. Проблема вызвана разницей в формате открытых ключей Диффи-Хеллмана Node.js и Java. Открытый ключ в Node.js является необработанным, но в Java он не является необработанным, поскольку к открытому ключу Java добавляются некоторые дополнительные метаданные. Итак, я решил точную проблему, создав открытый ключ, используя класс BigInteger с шестнадцатеричной строкой простого числа, генератора и открытого ключа, поступающего с моего TCP-сервера.

Вот мой Java-код для решения проблемы:

Socket socket = new Socket("185.255.95.248", 1211);
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[16384];
int bytesRead = inputStream.read(buffer);
String serverResponse = new String(buffer, 0, bytesRead);
JSONObject jsonObject = new JSONObject(serverResponse);
BigInteger publicKey = new BigInteger(jsonObject.getString("public_key"), 16);
BigInteger prime = new BigInteger(jsonObject.getString("prime"), 16);
BigInteger generator = new BigInteger(jsonObject.getString("generator"), 16);
DHParameterSpec spec = new DHParameterSpec(publicKey, prime, generator);
KeyFactory keyFactory = KeyFactory.getInstance("DH");
PublicKey key = keyFactory.generatePublic(spec);
Log.d("Public Key", Base64.encodeToString(key.getEncoded(), Base64.DEFAULT));

Вот мой код Node.js для решения этой проблемы:

const net = require("net");
const crypto = require("crypto");

const dh = crypto.createDiffieHellman(512);
const serverDiffieHellman = crypto.createDiffieHellman(dh.getPrime());

net.createServer((socket) => {
    socket.on("connect", () => socket.write(JSON.stringify({
    public_key: serverDiffieHellman.getPublicKey("hex"),
    prime: serverDiffieHellman.getPrime("hex"),
    generator: serverDiffieHellman.getGenerator("hex")
})));
}).listen(1211, "185.255.95.248", () => console.info("TCP server is running..."));

Другие вопросы по теме