TLSv1.2密钥交换算法安全性及性能比较(RSA, DHE, ECDHE)


想当初, 某次将服务器容器jetty升级之后, 公司的小霸王服务器直接就跪了, 当时还不知道 DHE, ECDHE是什么鬼. 只是通过分析jvm stack发现, 大量线程卡在这两个相关算法中. 于是果断地配置jetty, 这两个算法剔除掉了.
不过. ECDHE是趋势, 苹果公司指定要用这种算法, 等迫不得已的时候再开吧.
今天测试了一下 RSA, DHE, ECDHE这三种方式的性能.

先上总结

TLSv1.2密钥交换算法 安全性 本次测试耗时(秒)
RSA 低, 如果RSA私钥泄露或被破解, 全完蛋 0.1
DHE 较高, 即使RSA私钥泄露, 也没事. 即使某个人的连接被破解, 其他人也不受影响
算法难度等同于
解方程: 2e % p = q, 已知p和q , 求e等于多少?
23
ECDHE 很高. 同上.
算法难度等同于:
已知有限域椭圆曲线方程E, 曲线上两点g和Q, k * g = Q, 求k为多少?
28

测试DHE

分析:

  1. DH每次需要随机生成一个大素数p, 大指数e, 基数为固定值g=2
  2. 执行一次大数模幂运算 g e m o d   p g^e mod\ p , 算出公钥
  3. 使用对方的公钥q, 再次执行大数模幂运算, 计算出密钥key = q e m o d   p q^e mod\ p

测试代码如下.

    public static KeyPair genDHKeyPair() throws Exception {
        //KeyPairGenerator keyPairGeneator = KeyPairGenerator.getInstance("DH");
        //keyPairGeneator.initialize(1024);
        DHKeyPairGenerator keyPairGeneator = new DHKeyPairGenerator();
        keyPairGeneator.initialize(1024, RANDOM);
        KeyPair pair = keyPairGeneator.generateKeyPair();
        return pair;
    }
    public static void DHPerformance() throws Throwable {
        KeyPair clientKeyPair = genDHKeyPair();
        long time = System.currentTimeMillis();
        for (int i = 0; i < 1 * 10000; i++) {
            KeyPair serverKeyPair = genDHKeyPair();
            KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
            keyAgreement.init(serverKeyPair.getPrivate());
            keyAgreement.doPhase(clientKeyPair.getPublic(), true);
            keyAgreement.generateSecret();
        }
        logger.info("time: {}", System.currentTimeMillis() - time);
    }

耗时23秒

测试ECDHE

分析:

  1. 每次需要生成一个私钥(大数), 并计算椭圆方程的乘法, 得到公钥
  2. 拿到对方公钥之后, 本端私钥与对方公钥执行椭圆方程的乘法,

测试代码如下.

    public static KeyPair genECCKeyPair() throws Throwable {
        //KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
        ECGenParameterSpec spec = new ECGenParameterSpec("secp256r1");
        keyPairGenerator.initialize(spec, new SecureRandom());
        KeyPair pair = keyPairGenerator.generateKeyPair();
        return pair;
    }

    public static void ECDHEPerformance() throws Throwable {
        KeyPair clientPair = genECCKeyPair();
        long time = System.currentTimeMillis();
        for (int i = 0; i < 1 * 10000; i++) {
            KeyPair serverPair = genECCKeyPair();
            KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
            keyAgreement.init(serverPair.getPrivate());
            keyAgreement.doPhase(clientPair.getPublic(), true);
            keyAgreement.generateSecret();
        }
        logger.info("time: {}", System.currentTimeMillis() - time);
    }

耗时28秒

测试RSA

分析:
服务器已经有私钥和公钥, 只需要执行一次解密操作, 即一次大数模幂操作
测试代码

    public static KeyPair genRSAKeyPair() throws Exception {
        //KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        RSAKeyPairGenerator keyPairGenerator = new RSAKeyPairGenerator();
        keyPairGenerator.initialize(2048, RANDOM);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

    public static void RSAPerformance() throws Throwable {
        KeyPair serverKeyPair = genRSAKeyPair();
        Random r = new Random();
        byte[] preMaster = new byte[48];
        r.nextBytes(preMaster);
        Cipher encoder = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        encoder.init(Cipher.ENCRYPT_MODE, serverKeyPair.getPublic());
        encoder.update(preMaster);
        byte[] encryptedPreMaster = encoder.doFinal();
        long time = System.currentTimeMillis();
        for (int i = 0; i < 1 * 10000; i++) {
            Cipher decryptor = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            decryptor.init(Cipher.DECRYPT_MODE, serverKeyPair.getPublic());
            decryptor.update(encryptedPreMaster);
        }
        logger.info("time: {}", System.currentTimeMillis() - time);
    }

耗时 0.1秒

猜你喜欢

转载自blog.csdn.net/wzj_whut/article/details/86666147
今日推荐