Java 加密网络应用程序的安全方法

Java 加密网络应用程序的安全方法,java,security,aes,rsa,netty,Java,Security,Aes,Rsa,Netty,好的,我想知道我目前加密网络连接的方法(将在下面几行中解释)是安全有效的 此外,我还试图记住,我希望使用尽可能少的字节(传输),因为这可能用于Android 我目前的方法是使用两种加密方法:RSA(keysize=512)和AES(keysize=128) 我所做的是: 服务器生成RSA公钥和私钥 当客户端连接时,服务器向客户端发送公钥RSA 客户端生成AES密钥,并使用服务器提供的公共RSA密钥加密AES密钥 客户端发送加密的AES密钥,服务器使用专用RSA密钥解密加密的AES密钥 现在,如果

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

此外,我还试图记住,我希望使用尽可能少的字节(传输),因为这可能用于Android

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

我所做的是:

  • 服务器生成RSA公钥和私钥
  • 当客户端连接时,服务器向客户端发送公钥RSA
  • 客户端生成AES密钥,并使用服务器提供的公共RSA密钥加密AES密钥
  • 客户端发送加密的AES密钥,服务器使用专用RSA密钥解密加密的AES密钥
  • 现在,如果我是正确的,就不可能从客户端嗅探任何数据包,因为您不可能解密AES密钥(没有私钥)

    这是安全的方式吗?还是有什么后门

    这不是我唯一的问题

    因为我的应用程序是用Java构建的,所以总是可以对其进行反向工程。由于客户端生成AES密钥并将其保存在内存中,因此是否可以获得AES密钥

    最后问题: 使用以下代码生成密钥对需要大约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,300毫秒能买得起吗


    提前感谢。

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

    第二个问题是512位RSA密钥太小而不安全。一台现代台式PC机可以在不到一个月的时间内完成这一功能,而使用多台机器则可能需要数天/小时。当您每次生成一个新密钥时,如果某人只需要窃听连接,他们仍然可以轻松地记录流量,然后离线计算密钥

    关于访问内存中的AES密钥,是的,这是完全可能的,但是任何访问客户机进程内存的人在加密之前也可以访问明文数据。无论使用何种加密方法,这都将是一个问题,尽管确保密钥不会在其使用期之后保留在内存中会限制此类攻击的可能时间。然而,在Java这样的环境中,要实现这一点有些困难,在Java中,GC可以移动数据,并在内存中保留一个键的多个副本,即使使用后将键数据归零


    总之,我强烈建议您不要尝试发明自己的加密方案,而是使用现有的、成熟的、经过验证的方案,如SSL。我的专业知识不是Java,但我可以非常肯定的是,在API中存在建立SSL会话的方法。

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

    第二个问题是512位RSA密钥太小而不安全。一台现代台式PC机可以在不到一个月的时间内完成这一功能,而使用多台机器则可能需要数天/小时。当您每次生成一个新密钥时,如果某人只需要窃听连接,他们仍然可以轻松地记录流量,然后离线计算密钥

    关于访问内存中的AES密钥,是的,这是完全可能的,但是任何访问客户机进程内存的人在加密之前也可以访问明文数据。无论使用何种加密方法,这都将是一个问题,尽管确保密钥不会在其使用期之后保留在内存中会限制此类攻击的可能时间。然而,在Java这样的环境中,要实现这一点有些困难,在Java中,GC可以移动数据,并在内存中保留一个键的多个副本,即使使用后将键数据归零


    总之,我强烈建议您不要尝试发明自己的加密方案,而是使用现有的、成熟的、经过验证的方案,如SSL。我的专业知识不是Java,但我非常确定API中存在建立SSL会话的方法。

    谢谢,我睁开了眼睛。我想投赞成票,但我没有足够的声誉。谢谢,我睁开了眼睛。我会投赞成票,但我没有足够的声誉。