BouncyCastle ECDSA 签名需要几毫秒
BouncyCastle ECDSA signing takes several milliseconds
我必须使用以下参数创建大量签名,使用以下代码,使用 Intel Core i5-6500 CPU 创建签名大约需要 10 毫秒。
在普通 PC 上使用这些参数创建签名需要大约 10 毫秒是否正常?这次我该如何改进?如果每个签名能达到1ms,我会很高兴。
Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
g.initialize(ECNamedCurveTable.getParameterSpec("P-256"));
KeyPair keyPair = g.generateKeyPair();
Signature s = Signature.getInstance("SHA256withECDSA");
s.initSign(keyPair.getPrivate());
s.update("first".getBytes());
long start = System.currentTimeMillis();
s.sign(); // Takes about 30 msecs
System.out.println(System.currentTimeMillis() - start);
s.update("second".getBytes());
start = System.currentTimeMillis();
s.sign(); // Takes about 10 msecs for this and every further signature
System.out.println(System.currentTimeMillis() - start);
我已经尝试了here的建议,但我无法实现性能提升。
您的测试方法太离谱,结果没有任何意义:
- 应允许 JIT 编译器有一些启动时间,以便它可以编译和优化字节码;
- 需要(单独)执行许多符号和稍后的数据验证,然后计时并划分;
- 应使用纳米计时器或秒表实现;
update
应该是签名生成操作的一部分(或者完全省略,签署空字符串);
- ECDSA 使用 SecureRandom 实现来计算签名,这可能会影响结果(最好提供一个具体的);
- 请注意,您可能希望将结果用于某些事情,因为智能编译器可能会以其他方式优化整个签名生成。
最后,从性能上来说:
- Java 9月起更新了
BigInteger
使用本机代码(内部函数)实现,这可能会对软件中的任何非对称操作产生巨大影响;
- 标准 SunEC 提供程序也可以与您的曲线一起使用并且更有可能表现良好,同样因为它可能在下面使用本机指令(编辑:但在我使用 BC 版本 1.57 的系统上它几乎是 慢!).
因此请注意,结果高度依赖于环境和 CPU 使用(写下来!)。
您应该使用 Signature.getInstance("SHA256withECDSA", "BC")
以便实际使用 Bouncy Castle 提供程序 - 如果您不这样做并且 Bouncy 仍在使用,那么您可能已经在 JRE 本身中配置了另一个 Bouncy Castle 提供程序(在安全文件夹),因此如果该版本与类路径中的版本不同,结果可能会有所不同。
出于某种原因,仅为密钥对生成器指定 "EC"
可能比 "ECDSA"
更兼容不同的提供商。
最后,这里有一些东西可以比较:
$ openssl speed ecdsap256
Doing 256 bit sign ecdsa's for 10s: 147861 256 bit ECDSA signs in 9.98s
Doing 256 bit verify ecdsa's for 10s: 78064 256 bit ECDSA verify in 10.00s
OpenSSL 1.0.2j 26 Sep 2016
built on: reproducible build, date unspecified
options:bn(64,64) md2(int) rc4(16x,int) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx)
compiler: gcc -I. -I.. -I../include -D_WINDLL -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -DDSO_DLFCN -DHAVE_DLFCN_H -ggdb -O2 -pipe -Wimplicit-function-declaration -fdebug-prefix-map=/usr/src/ports/openssl/openssl-1.0.2j-1.x86_64/build=/usr/src/debug/openssl-1.0.2j-1 -fdebug-prefix-map=/usr/src/ports/openssl/openssl-1.0.2j-1.x86_64/src/openssl-1.0.2j=/usr/src/debug/openssl-1.0.2j-1 -DTERMIOS -DL_ENDIAN -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DRC4_ASM -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
sign verify sign/s verify/s
256 bit ecdsa (nistp256) 0.0001s 0.0001s 14809.8 7806.4
在我基于 i7 的低端笔记本电脑上:
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 61
model name : Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz
stepping : 4
cpu MHz : 2394.000
cache size : 256 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 20
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe pni dtes64 monitor ds_cpl vmx est tm2 ssse3 fma cx16 xtpr pdcm sse4_1 sse4_2 x2apic movbe popcnt aes xsave osxsave avx f16c rdrand lahf_lm ida arat epb xsaveopt pln pts dtherm fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap
clflush size : 64
cache_alignment : 64
address sizes : 39 bits physical, 48 bits virtual
power management:
我必须使用以下参数创建大量签名,使用以下代码,使用 Intel Core i5-6500 CPU 创建签名大约需要 10 毫秒。
在普通 PC 上使用这些参数创建签名需要大约 10 毫秒是否正常?这次我该如何改进?如果每个签名能达到1ms,我会很高兴。
Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
g.initialize(ECNamedCurveTable.getParameterSpec("P-256"));
KeyPair keyPair = g.generateKeyPair();
Signature s = Signature.getInstance("SHA256withECDSA");
s.initSign(keyPair.getPrivate());
s.update("first".getBytes());
long start = System.currentTimeMillis();
s.sign(); // Takes about 30 msecs
System.out.println(System.currentTimeMillis() - start);
s.update("second".getBytes());
start = System.currentTimeMillis();
s.sign(); // Takes about 10 msecs for this and every further signature
System.out.println(System.currentTimeMillis() - start);
我已经尝试了here的建议,但我无法实现性能提升。
您的测试方法太离谱,结果没有任何意义:
- 应允许 JIT 编译器有一些启动时间,以便它可以编译和优化字节码;
- 需要(单独)执行许多符号和稍后的数据验证,然后计时并划分;
- 应使用纳米计时器或秒表实现;
update
应该是签名生成操作的一部分(或者完全省略,签署空字符串);- ECDSA 使用 SecureRandom 实现来计算签名,这可能会影响结果(最好提供一个具体的);
- 请注意,您可能希望将结果用于某些事情,因为智能编译器可能会以其他方式优化整个签名生成。
最后,从性能上来说:
- Java 9月起更新了
BigInteger
使用本机代码(内部函数)实现,这可能会对软件中的任何非对称操作产生巨大影响; - 标准 SunEC 提供程序也可以与您的曲线一起使用并且更有可能表现良好,同样因为它可能在下面使用本机指令(编辑:但在我使用 BC 版本 1.57 的系统上它几乎是 慢!).
因此请注意,结果高度依赖于环境和 CPU 使用(写下来!)。
您应该使用 Signature.getInstance("SHA256withECDSA", "BC")
以便实际使用 Bouncy Castle 提供程序 - 如果您不这样做并且 Bouncy 仍在使用,那么您可能已经在 JRE 本身中配置了另一个 Bouncy Castle 提供程序(在安全文件夹),因此如果该版本与类路径中的版本不同,结果可能会有所不同。
出于某种原因,仅为密钥对生成器指定 "EC"
可能比 "ECDSA"
更兼容不同的提供商。
最后,这里有一些东西可以比较:
$ openssl speed ecdsap256
Doing 256 bit sign ecdsa's for 10s: 147861 256 bit ECDSA signs in 9.98s
Doing 256 bit verify ecdsa's for 10s: 78064 256 bit ECDSA verify in 10.00s
OpenSSL 1.0.2j 26 Sep 2016
built on: reproducible build, date unspecified
options:bn(64,64) md2(int) rc4(16x,int) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx)
compiler: gcc -I. -I.. -I../include -D_WINDLL -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -DDSO_DLFCN -DHAVE_DLFCN_H -ggdb -O2 -pipe -Wimplicit-function-declaration -fdebug-prefix-map=/usr/src/ports/openssl/openssl-1.0.2j-1.x86_64/build=/usr/src/debug/openssl-1.0.2j-1 -fdebug-prefix-map=/usr/src/ports/openssl/openssl-1.0.2j-1.x86_64/src/openssl-1.0.2j=/usr/src/debug/openssl-1.0.2j-1 -DTERMIOS -DL_ENDIAN -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DRC4_ASM -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
sign verify sign/s verify/s
256 bit ecdsa (nistp256) 0.0001s 0.0001s 14809.8 7806.4
在我基于 i7 的低端笔记本电脑上:
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 61
model name : Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz
stepping : 4
cpu MHz : 2394.000
cache size : 256 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 20
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe pni dtes64 monitor ds_cpl vmx est tm2 ssse3 fma cx16 xtpr pdcm sse4_1 sse4_2 x2apic movbe popcnt aes xsave osxsave avx f16c rdrand lahf_lm ida arat epb xsaveopt pln pts dtherm fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap
clflush size : 64
cache_alignment : 64
address sizes : 39 bits physical, 48 bits virtual
power management: