1

我正在尝试使用 RSA 预共享密钥进行通信,理想情况下,涉及信任库恶作剧

设置基本上是这样的:

客户端有一个小程序,服务器端有一个 servlet(duh :))

小程序有 servlet 的 RSA 公钥 (Spub) 硬编码。

servlet 有自己的 RSA 私钥 (Spriv) 硬编码。

他们的小程序生成一个随机的 AES 256 密钥(会话密钥),用 servlet 的公钥(它已经硬编码)对其进行加密,通过 TCP 套接字连接到 servlet,并将 RSA 加密的密钥发送到 servlet,后者继续解密会话密钥并将其用于与此小程序的任何进一步通信,只要此套接字连接持续。

我宁愿在不弄乱信任库之类的情况下完成这一切(毕竟,这是一个相对简单的设置,允许预共享的硬编码公钥)

关于我应该从哪里开始自我教育的任何建议?

4

2 回答 2

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);
    }
}
于 2012-07-07T05:17:31.417 回答
2

尽管您可以通过构建PublicKey和使用来使用较低级别的加密函数Cipher,但值得考虑使用 JSSE:它将在套接字的上下文中提供所有这些。此外,SSL/TLS 提供的加密是通过在握手期间协商的共享密钥完成的(除其他外,它比非对称加密更快)。

您可以使用自签名证书构建一个信任库,用于预共享该公钥。您可以按如下方式加载它(注意InputStream不一定是 a 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):这肯定会使代码更长更复杂。

如果你在一个小程序中运行所有这些,你可能仍然有关于小程序权限系统的问题,以建立套接字连接。请参阅小程序可以做什么和不能做什么

于 2012-07-07T14:38:29.540 回答