Подписание BouncyCastle ECDSA занимает несколько миллисекунд - PullRequest
0 голосов
/ 11 мая 2018

Мне нужно создать много подписей с указанными ниже параметрами, и с помощью следующего кода для создания подписи с процессором Intel Core i5-6500 требуется около 10 мсек.

Нормально ли для создания подписей с этими параметрами занимать около 10 мс на обычном ПК?Как я мог улучшить это время?Я был бы очень рад получить 1 мс на подпись.

    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);

Я попробовал предложения из здесь , но не смог добиться повышения производительности.

1 Ответ

0 голосов
/ 11 мая 2018

Ваш метод тестирования настолько далек, что результаты ничего не значат:

  • JIT-компилятору должно быть разрешено некоторое время запуска, чтобы он мог компилировать и оптимизировать байт-код;
  • необходимо выполнить много знаков, а затем проверять данные (отдельно), затем это время и разделить;
  • следует использовать реализацию нано-таймера или секундомера;
  • update должен быть частью операции генерации подписи (или полностью исключен, подписывая пустую строку);
  • ECDSA использует реализацию SecureRandom для вычисления подписи, которая может повлиять на результат (лучше указать конкретную);
  • Помните, что вы можете захотеть использовать результат для чего-то, так как в противном случае умные компиляторы могут оптимизировать полное создание подписи.

Наконец, с точки зрения производительности:

  • Java 9 и далее обновили BigInteger реализация с собственным кодом (встроенными функциями), который может иметь огромное значение для любых асимметричных операций в программном обеспечении;
  • стандартный поставщик SunEC также может использоваться с вашей кривой и, скорее всего, будет работать хорошо, опять же, потому что он может использовать встроенные инструкции внизу (РЕДАКТИРОВАТЬ: но в моей системе, использующей версию BC 1.57, это почти в 10 раз больше, чем медленно !).

Обратите внимание, что результаты сильно зависят от среды и используемого процессора (запишите их!).


Вам следует использовать Signature.getInstance("SHA256withECDSA", "BC"), чтобы поставщик Bouncy Castle действительно использовался - если вы этого не сделаете, а Bouncy все еще используется, возможно, вы настроили другого поставщика Bouncy Castle в самой JRE (в папке безопасности) поэтому результаты могут отличаться, если это версия, отличная от указанной в вашем пути к классам.

Простое указание "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:
...