【问题标题】:Safe way to encrypt a network application加密网络应用程序的安全方法
【发布时间】:2014-06-02 06:01:10
【问题描述】:

好的,我想知道我目前加密网络连接的方法(将在接下来的几行中解释)是安全有效的。

另外我想记住,我想使用尽可能少的字节(传输),因为这可能用于 Android。

我目前的方法是使用两种加密方法:RSA(keysize= 512) 和 AES(keysize= 128)

我所做的是:

  1. 服务器生成一个 RSA 公钥和一个私钥。
  2. 当客户端连接时,服务器将公共 RSA 密钥发送给客户端。
  3. 客户端生成一个 AES 密钥并使用服务器提供的公共 RSA 密钥对 AES 密钥进行加密。
  4. 客户端发送其加密的 AES 密钥,服务器使用私有 RSA 密钥解密加密的 AES 密钥。

现在,如果我是正确的,就不可能从客户端嗅探任何数据包,因为您不可能解密 AES 密钥(没有私钥)。

这是一种安全的方式吗?还是某处有某种后门?

这不是我唯一的问题;

因为我的应用程序是用 Java 构建的,所以总是可以对其进行逆向工程。既然客户端生成了 AES Key 并保存在内存中,那么是否有可能拿到 AES Key?

最后一个问题: 使用此代码生成密钥对大约需要 300 毫秒:

我想听听你们的意见和/或改进。

private RSAKeySet(RSAPublicKey publicKey, PrivateKey privateKey) {
    this.publicKey = publicKey;
    this.privateKey = privateKey;

    byte[] mod = publicKey.getModulus().toByteArray();
    byte[] exp = publicKey.getPublicExponent().toByteArray();

    localPublicKeySpec = ByteBuffer.allocate(mod.length + exp.length + 8);
    localPublicKeySpec.putInt(mod.length);
    localPublicKeySpec.put(mod);
    localPublicKeySpec.putInt(exp.length);
    localPublicKeySpec.put(exp);
    localPublicKeySpec.flip();
}

public static final RSAKeySet generateKeys(int keySize) throws GeneralSecurityException {
    RSAKeySet set;
    long start = System.currentTimeMillis();
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");

    kpg.initialize(keySize);
    KeyPair kp = kpg.genKeyPair();
    set = new RSAKeySet((RSAPublicKey) kp.getPublic(), kp.getPrivate());

    System.err.println("RSA keys generated (" + (System.currentTimeMillis() - start) + "ms)");
    return set;
}

我用的是 Netty,300ms 能负担得起吗?

提前致谢。

【问题讨论】:

    标签: java security aes rsa netty


    【解决方案1】:

    不,这不安全 - 您的方案在第 1 步被破坏,因为您无法保证您收到的公钥是由服务器生成的,或者是由中间人拦截生成的流量并在将数据发送到真实服务器之前进行窃听或更改数据。

    第二个问题是 512 位 RSA 密钥太小而无法安全。一台现代台式电脑可以在不到一个月的时间内考虑到这样的密钥,而多台机器可能会缩短到几天/几小时。虽然您每次都在生成一个新密钥,但有人仍然可以轻松记录流量,然后如果他们只需要窃听连接,就可以离线分解密钥。

    关于访问内存中的 AES 密钥,是的,这是完全可能的,但是任何可以访问客户端进程内存的人也可以在明文数据被加密之前访问它。无论使用何种特定的加密方法,这都会成为一个问题,尽管确保密钥不会在超过其使用期限后保留在内存中将限制可能发生此类攻击的期限。然而,这在 Java 之类的东西中实现起来有点困难,其中 GC 可以移动数据并在内存中留下多个密钥副本,即使您在使用后将密钥数据归零。

    总之,我强烈建议您不要尝试发明自己的加密方案,而应使用现有的、完善的、经过验证的方案,例如 SSL。我的专长不是 Java,但我很确定 API 中存在建立 SSL 会话的方法。

    【讨论】:

    • 谢谢,让我大开眼界。我会投票,但我没有足够的声誉。
    猜你喜欢
    • 2017-08-12
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 2019-10-26
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    相关资源
    最近更新 更多