Разработка программного обеспечения, разработка мобильных приложений
Главная \ Новости \ ПАТЧИМ GNUPG ИЛИ ПАРА RSA-32768 ЗА 106 МИНУТ

Новости

« Назад

ПАТЧИМ GNUPG ИЛИ ПАРА RSA-32768 ЗА 106 МИНУТ 28.02.2016 05:13

Когда-то давным давно, чтобы использовать 8192 и 16384 RSA ключи я правил размер в keygen.c и размер SECMEM буффера по соседству. Дела давно минувших дней, теперь SECMEM вынесена в config.h и именуется SECMEM_BUFFER_SIZE.

В итоге после скачивания верии 2.0.29 под свежий debian 8.3, за место убитой 12й убунты апдейтом на 14ую, я быстренько подкрутил размер ключика и размер буфера и радостно сгенерировал на 5200U 16кбит ключ за 18 (или 19) минут, что раньше занимало 45-50 минут на P6200.

Но вот 32кбит дали мне пачку ошибок. Свободное время есть — разбираемся.

Первое, что бросается в глаза, это жестко прописанный размер при выделении SECMEM'ов. Вот несколько:

agent/gpg-agent.c: gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0); — 4 килобайта (так как эта реализация использует значение в битах)
scd/scdaemon.c: gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
tools/gpg-check-pattern.c: gcry_control (GCRYCTL_INIT_SECMEM, 4096, 0);

В принципе экономия памяти дело хорошее… с другой стороны если памяти хватает, почему не выделить полный объем, равный константе SECMEM_BUFFER_SIZE.

Далее в программе полно мест где фигурируют то 4кб ключи или связанные с ними (выделение буфера на чтение, или создания «пакета» для записи), привожу несколько:

agent/command-ssh.c: log_error (_("ssh keys greater than %d bits are not supported\n"), 4096);
g10/card-util.c: n = get_data_from_file (args, 16384, &data);
g10/plaintext.c: byte *buffer = xmalloc( 32768 );
common/dns-cert.c: rc=get_dns_cert (argv[1],16384,&iobuf,&fpr,&fpr_len,&url);

Сам размер ключа, который программа ест, задается в g10/keygen.c:

const unsigned maxsize = (opt.flags.large_rsa ? 8192 : 4096);
unsigned int nbits, min, def = DEFAULT_STD_KEYSIZE, max=4096;

Но, исправив исходники gnupg при генерации ключа RSA-32768 мы получим:

gpg: checking the trustdb
gpg: keyring_get_keyblock: read error: Invalid packet
gpg: keyring_get_keyblock failed: Invalid keyring
gpg: failed to rebuild keyring cache: Invalid keyring
gpg: keydb_search failed: Invalid packet
gpg: public key of ultimately trusted key FB2E6BDF not found
gpg: keyring_get_keyblock: read error: Invalid packet
gpg: keydb_get_keyblock failed: Invalid keyring
gpg: keydb_search failed: Invalid keyring
gpg: public key of ultimately trusted key 6146D68D not found
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: keyring_get_keyblock: read error: Invalid packet
gpg: keydb_get_keyblock failed: Invalid keyring
gpg: validate_key_list failed


Дьявол кроется в деталях в libgcrypt:

mpi/mpicoder.c: #define MAX_EXTERN_MPI_BITS 16384 — размер пакета в битах.

И в некоем роде:
src/secmem.c: #define MINIMUM_POOL_SIZE 16384
src/secmem.c: #define STANDARD_POOL_SIZE 32768
В некоем потому, что, как я понял из кода, это размер пула для SECMEM в байтах, в котором gnupg инициализирует свой securememory через gcry_control (GCRYCTL_INIT_SECMEM, размер_в_битах, 0);

В конечном итоге модификация вылилась вот в такой diff для GnuPG-2.0.29

gnupg-2.0.29-RSA32k.patch



До кучи увеличен максимальный размер сертификата и ключа для ssh.

И вот такой diff для libgcrypt-1.6.5

libgcrypt-1.6.5-RSA32k.patch


Размер пула был удвоен. Для почти безглюковых 16384 ключей размер пула был 32768 (при норме ключей в 4096 и 8192).

Работает ли сие?

Да:

sec 32768R/18B54A62 2016-02-24

uid test32768key

ssb 32768R/1507CD2A 2016-02-24


Производительность на i5-5200 под Debian 8.3 (4.3.0-0.bpo.1-amd64 #1 SMP Debian 4.3.3-7~bpo8+1 (2016-01-19) x86_64 GNU/Linux):

RSA 16384 — 19 минут (время генерации пары)

RSA 32768 — 106 минут (время генерации пары)


Шифрование файла размером 12Мб (другой ключ RSA-32768, за время тестов и написания я их штук 10 нагенерил):

time gpg2 --out file.gz.enc --recipient «test32768pair» --encrypt file.gz

real 0m0.079s

user 0m0.072s

sys 0m0.004s


Дешифровка:

time gpg2 --out file.gz.gz --decrypt file.gz.enc

real 0m7.610s

user 0m5.624s

sys 0m0.024s


И проверка:

7ab98fd4a154fad5f5bbe0d698178783cd2ac994 file.gz

9773bb1b9d7f75f408f562d476e8936aafa0f3b9 file.gz.enc

7ab98fd4a154fad5f5bbe0d698178783cd2ac994 file.gz.gz


Тонкости: если в кейринг добавить такой ключ, то ванильная версия не будет читать, в виду описанного выше (mpi и т.д.). Так что при использовании такой версии (модифицированной) и использовании ванильного софта (который работает с классическими ключами) надо создавать отдельный кейринг.

Ну и, как обычно: ВОЗМОЖНЫ ПОТЕРЯ ДАННЫХ, КРАХ СИСТЕМЫ И КРАСНЫЕ ГЛАЗА.

Ссылки на проект и патчи (=diff) на github:


Удачи и при наличии вопросов я готов на них ответить, со своих двухлетним опытом C который был 15 лет назад!

Так же выслушаю замечания по улучшению модификации.

Вопрос: зачем RSA-32768, вам что RSA-(2048|4096|8192|16384) мало?

Ответ: потому, что *можно!

*современное железо вполне себе позволяет работать с большими ключами без ощутимых проблем. Даже ноутбучное. Призывать использоват RSA-32768 я не буду, но иметь такой большой ключ и пачку сабключей идея неплохая, как и шифровать особо критичные данные, пока великий КвантовыйКомпьютер не покорал мир простых чисел!

 

Источник: https://habrahabr.ru/post/278051/

 


Комментарии


Комментариев пока нет

Пожалуйста, авторизуйтесь, чтобы оставить комментарий.
Авторизация
Введите Ваш логин или e-mail:

Пароль:
запомнить

Адрес:
Москва
Телефон: