AES-NI加速密码学计算

AES-NI指令集

AES-NI是一个x86指令集架构的扩展,用于Intel和AMD微处理器,由Intel在2008年3月提出。[1]该指令集的目的是改进应用程序使用高级加密标准(AES)执行加密和解密的速度。这项技术在从企业级的大数据、区块链到个人用的NAS等都用得上.

如何检查cpu是否支持该功能

$ cat /proc/cpuinfo | grep aes | wc -l

如果支持,应该是4核,得出的统计结果也是4

//我家15年的占美移动i5-4200U CPU @ 1.60GHz 居然也支持;但是13年的笔记本上不支持

//工作笔记本i5-5200U不支持

成功的对比测试

用了openssl命令,终于发现开启aes-ni有明显区别。版本:OpenSSL 1.0.2g 1 Mar 2016


$ openssl speed -elapsed -evp aes-256-cbc

$ OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -evp aes-256-cbc

$ openssl speed -elapsed -evp aes-128-cbc

$ OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -evp aes-128-cbc

|是否开启|type |16 bytes | 64 bytes | 256 bytes | 1024 bytes |8192 bytes|

|———–|—————–|————-|—————|—————|——————-|—————|

|是 |aes-256-cbc | 364209.02k| 398876.69k | 401026.39k | 398883.84k | 411863.72k|

|否 |aes-256-cbc | 167362.41k | 183630.57k | 188587.43k | 181141.16k | 192430.08k|

|是 |aes-128-cbc | 496741.25k | 549389.38k | 541275.99k | 568249.34k | 557129.73k|

|否 |aes-128-cbc | 228221.45k | 253612.69k | 261900.12k | 252299.61k | 267665.41k|

戏剧场面:如上占美机cpu比工作笔记本差,但是开启了AES-NI反而性能好

|是否开启|type |16 bytes | 64 bytes | 256 bytes | 1024 bytes |8192 bytes|

|———–|—————–|————-|—————|—————|——————-|—————|

|是 |aes-256-cbc |164328.05k | 185898.77k | 188741.03k | 189848.23k | 191176.70k|

|否 |aes-256-cbc |172242.04k | 185854.25k | 189062.06k | 190826.84k | 190308.35k|

|是 |aes-128-cbc |234664.05k | 254232.28k | 262027.18k | 264717.31k | 266376.53k|

|否 |aes-128-cbc |230932.81k | 258159.45k | 260335.87k | 265747.80k | 266283.69k|

肌肉机53在相同测试下的表现

|是否开启|type |16 bytes | 64 bytes | 256 bytes | 1024 bytes |8192 bytes|

|———–|—————–|————-|—————|—————|——————-|—————|

|是 |aes-256-cbc |368562.35k |422608.32k |422655.83k |428560.38k | 432821.59k|

|否 |aes-256-cbc |163098.28k |199936.81k |201100.63k |203751.77k |204423.17k|

|是 |aes-128-cbc |490116.30k |588865.32k |541665.28k |592911.02k |601513.98k|

|否 |aes-128-cbc |225345.57k |273998.44k |280313.77k |284544.00k |285297.32k|


Java对AES-NI是默认支持的吗?(答案:是的,前提是这台机器的硬件支持)

重要文章解释如何在Linux上Java开启AES-NI


Hardware intrinsics were added to use Advanced Encryption Standard (AES). The UseAES and UseAESIntrinsics flags are available to enable the hardware-based AES intrinsics for Intel hardware. The hardware must be 2010 or newer Westmere hardware.

最重要的几点:1.确认cpu支持 2. 和class的编译无关,是运行时的一种技术 3.默认打开的


//如果是打开支持

-XX:+UseAES -XX:+UseAESIntrinsics
//如果是取消支持

-XX:-UseAES -XX:-UseAESIntrinsics
//查看是否已经打开了jvm的AES-NI支持选项,结果显示23已经打开,工作笔记本未开(其他服务器,包括北软的也是打开的);家里的占美机是打开的

$ java -XX:+PrintFlagsFinal -version | grep AES

AES-NI may only be available on the server VM.


AESNI实测效果

准备对比:工作笔记本没有AES-NI,但是cpu是i5-5200U,比53肌肉机服务器至强(Intel(R) Xeon(R) CPU E5-2660 v4 @ 2.00GHz)频率更高,如果同样的class运行出来效果比工作笔记本好,说明是AES-NI起了作用;然后在服务器上关闭AESNI试试

  • 工作笔记本是2.2Ghz的cpu,频率比服务器的至强2.0Ghz还要高点,但是工作笔记本是没有AESNI指令集的,加密AES一亿次需要的时间要75秒,相反服务器上同样的代码只要30秒

  • 而且服务器上也可以关闭AESNI指令集,时间也变为75秒。强烈的对比,开启与否一倍的差距


[root@vm-yjy-36 blockchain]# java AESNITester

Begin ..

End .. 耗时:30517

[root@vm-yjy-36 blockchain]# java AESNITester

Begin ..

End .. 耗时:29570

[root@vm-yjy-36 blockchain]# java -XX:-UseAES -XX:-UseAESIntrinsics AESNITester

Begin ..

End .. 耗时:78823

[root@vm-yjy-36 blockchain]# java -XX:-UseAES -XX:-UseAESIntrinsics AESNITester

Begin ..

End .. 耗时:75427

附:测试文件的源代码



import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class AESNITester {

    private static final String PLAINTEXT = "ZZZLOVEXUXUANDHENRYZZZLOVEXUXUANDHENRY";

    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        long begintime = System.currentTimeMillis();
        System.out.println("Begin ..");
        //1.生成随机数
        SecureRandom srandom = new SecureRandom();
        //2.向量
        byte[] iv = new byte[128/8];
        srandom.nextBytes(iv);
        IvParameterSpec ivspec = new IvParameterSpec(iv);
        //3.密钥
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecretKey skey = kgen.generateKey();
        //4.初始化
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skey, ivspec);
        //5.开始加密
        for (int i=0; i<100000000; i++) {
            byte[] ciphered = cipher.doFinal(PLAINTEXT.getBytes());
        }
        System.out.println("End .. 耗时:" + (System.currentTimeMillis() - begintime));

//        System.out.println("加密前长度:" + PLAINTEXT.length() + " 加密后长度:" + ciphered.length);
//        cipher.init(Cipher.DECRYPT_MODE, skey, ivspec);
//        byte[] recovered = cipher.doFinal(ciphered);
//        System.out.println("解密成功:" + new String(recovered));
    }
}
最终确认肌肉机上已经用上了AES-NI指令

验证服务器上用的已经使用了AESNI指令(见如下53机上对比测试,纯加密时间也节约一半),但是从doFinal到整体,还是有很多工作的,比如密钥初始化,向量初始化,随机数生成,纯加密提升100%,但是算上这些前期初始化工作,提升不到10%,也就是说纯加密计算在整体密码模块中运行也只占一部分左右,这也是为什么之前估计偏差


java -cp .:./ethereumj-core-1.5.0-SNAPSHOT-all.jar AESSpongyTester

End ..3694

java -XX:-UseAES -XX:-UseAESIntrinsics -cp .:./ethereumj-core-1.5.0-SNAPSHOT-all.jar AESSpongyTester

End ..9513

注意:

  • 1.编译成整个jar包,所需要的类都在里面了。javac时要加上这个jar为classpath

  • 2.运行时classpath要进一步加上本地目录(也就是这个孤零零的测试类在的目录)

猜你喜欢

转载自blog.csdn.net/wxid2798226/article/details/79303711
今日推荐