Вопрос по encryption, cryptography, encryption-asymmetric, truststore, java – Java - асимметричное шифрование трафика с предварительно открытыми общими ключами и без проблем с хранилищем доверия

1

Я пытаюсь связаться с помощью общих ключей RSA и, в идеале,without с участием трастовских махинаций

Настройка в основном так:

There's an applet on client side and a servlet on server side (duh :) )

The applet has servlet's RSA public key (Spub) hardcoded.

The servlet has it's own RSA private key (Spriv) hardcoded.

They applet generates a random AES 256 key (session key), encrypts it with servlet's public key (which it has hardcoded), connects to the servlet over a TCP socket and sends the RSA-encrypted key to the servlet, which proceeds to decrypt the session key and use it for any further communication with this applet as long as this socket connection lasts.

Я бы предпочел сделать все это, не связываясь с хранилищем доверенных сертификатов и тому подобным (в конце концов, это относительно простая настройка, которая допускает использование предварительно открытого общего ключа в жестком коде)

Какие-нибудь предложения относительно того, где я должен начать искать самообразование?

Ух ты, не понял, что могу сделать хранилище ключей в памяти. Спасибо Owlstead и ДНК! Black
Апплет загружен через HTTPS? SLaks
Как сказал owlstead - вы можете использовать хранилище ключей в памяти, используя что-то вродеKeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()) и затем импортируйте свой жестко закодированный ключ / сертификат. DNA
Нету. Это, однако, подписанный апплет. Зачем ? :) Black
Вы можете использовать встроенный SSL (JSSE), если просто создаете самозаверяющий сертификат для своего клиента и сервера. Java SSL имеет много точек расширения, и вы можете просто создать хранилище доверенных сертификатов в памяти. Maarten Bodewes

Ваш Ответ

2   ответа
2

Хотя вы можете использовать низкоуровневые криптографические функции, создавPublicKey и используяCipherСтоит рассмотреть вопрос об использовании JSSE: он предоставит все это в контексте сокетов. Кроме того, шифрование, обеспечиваемое SSL / TLS, выполняется посредством общих ключей, согласованных во время рукопожатия (среди прочего, это быстрее, чем асимметричное криптографическое шифрование).

Вы можете создать доверенное хранилище с самозаверяющим сертификатом для предварительного обмена этим открытым ключом. Вы можете загрузить его следующим образом (обратите внимание, чтоInputStream не обязательно должен бытьFileInputStreamВы можете прочитать содержимое из памяти, например):

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
InputStream is = ...
ks.load(is, null);
// or ks.load(is, "thepassword".toCharArray());
is.close();

tmf.init(ks);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

SSLSocketFactory = sslContext.getSocketFactory();
// ...

Это нормальный способ использования JSSE. Если вы хотите использовать SSL / TLS с вашим явным открытым ключом RSA, вам придется реализовать свой собственныйTrustManager сделать явное сравнение (вместо использованияTrustManagerFactory): это, безусловно, сделает код немного длиннее и сложнее.

Если вы запустите все это в апплете, у вас все еще могут возникнуть проблемы с системой разрешений апплета, чтобы устанавливать сокет-соединения. УвидетьWhat Applets Can and Cannot Do.

2

Я бы согласился с комментариями о том, что SSL - достойный путь, но чтобы ответить на ваш прямой вопрос, описанная вами схема довольно проста и, похоже, не раскрывает никаких секретов. Вот реализация RSA-части клиента на основе жестко закодированного открытого ключа.

// Hardcoded values extracted from getModulus of a generated KeySpec.
private static BigInteger mod = new BigInteger("113...");
private static BigInteger exp = new BigInteger("217...");

private PublicKey hardCodedKey() {
    RSAPublicKeySpec keySpec = new RSAPublicKeySpec(mod, exp);
    KeyFactory keyFactory = null;
    PublicKey rsaKey = null;
    try {
        keyFactory = KeyFactory.getInstance("RSA");
        rsaKey = keyFactory.generatePublic(keySpec);
    } catch (Exception ex) {
        throw new IllegalStateException(ex);
    }
    return rsaKey;
}

private byte[] encrypt(PublicKey pubKey, byte[] plaintext) {
    try {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return cipher.doFinal(plaintext);
    } catch (Exception ex) {
        throw new IllegalStateException(ex);
    }
}
Большое спасибо! Я думаю, что попробую это, затем попробую доверенное хранилище в памяти (не понимал, что это можно сделать) и посмотрим, есть ли причины использовать одну или другую. Black

Похожие вопросы