Что касается команды OpenSSL для генерации ключей RSA (128 бит)

Bai Bing спросил: 28 марта 2018 в 01:49 в: openssl

Я использую OpenSSL версии 1.0.2j

$ openssl version
OpenSSL 1.0.2j  26 Sep 2016

Я генерирую 32-разрядный ключ для цели обучения:

$ openssl genrsa -out key.pem 32; openssl rsa -in key.pem -text -noout
Generating RSA private key, 32 bit long modulus
.+++++++++++++++++++++++++++
.+++++++++++++++++++++++++++
e is 65537 (0x10001)
Private-Key: (32 bit)
modulus: 3049905109 (0xb5c9dbd5)
publicExponent: 65537 (0x10001)
privateExponent: 643259637 (0x26575cf5)
prime1: 59747 (0xe963)
prime2: 51047 (0xc767)
exponent1: 34201 (0x8599)
exponent2: 28991 (0x713f)
coefficient: 570 (0x23a)

Я протестировал 59747 51047 == 3049905109, так что это правильно.

Затем я попытался сгенерировать 128 бит:

$ openssl genrsa -out key.pem 128; openssl rsa -in key.pem -text -noout
Generating RSA private key, 128 bit long modulus
.....+++++++++++++++++++++++++++
.+++++++++++++++++++++++++++
e is 65537 (0x10001)
Private-Key: (128 bit)
modulus:
    00:d7:f5:7b:f4:ac:b3:d6:ab:69:e9:f8:46:89:80:
    ad:a7
publicExponent: 65537 (0x10001)
privateExponent:
    00:96:69:0e:9d:5a:0f:a3:49:d5:f2:7f:5b:d5:bd:
    d5:71
prime1: 4077820879 (0xf30e9bcf)
prime2: 1063358121 (0x3f618ea9)
exponent1: 843651503 (0x324919af)
exponent2: 245467033 (0xea18799)
coefficient: 3957324193 (0xebdff9a1)

Ясно 0xf30e9bcf 0x3f618ea9 = 3C2D38538980ADA7, но модуль равен 00d7f57bf4acb3d6ab69e9f8468980ada7.

Похоже, что последние 8 шестнадцатеричных цифр верны, но другие не совпадают. Я смущен, почему это произойдет. Может ли кто-нибудь объяснить это?

1 ответ

bartonjs ответил: 28 марта 2018 в 03:39

Команда печати, похоже, запуталась, и она напечатала prime1 и prime2 (и друзей) в виде 32-битных значений вместо 64-битных.

Факторизация D7F57BF4ACB3D6AB69E9F8468980ADA7 равна F798F9F1F30E9BCF DF49A5063F618EA9.

Команда OpenSSL напечатала нижние 32 бита каждого из простых чисел факторы, а не полные 64 бита.

Поскольку в этом умножении нет мода, нижние 32 бита результата верны с усеченными значениями, просто из-за умножения. (Вспомните, как записать умножение двух длинных чисел в длинную форму ... теперь сделайте это в шестнадцатеричном формате).

Я выполнил команду много раз, и она всегда печатала 64-битные значения значений CRT:

$ openssl genrsa 128 | openssl rsa -text
Generating RSA private key, 128 bit long modulus
.+++++++++++++++++++++++++++
...+++++++++++++++++++++++++++
e is 65537 (0x10001)
Private-Key: (128 bit)
modulus:
    00:e9:e2:0f:ed:54:89:0c:e7:4c:a0:c5:52:8f:c3:
    85:c3
publicExponent: 65537 (0x10001)
privateExponent:
    00:b5:bc:a8:dd:a5:3b:9d:9e:bd:80:57:b6:b2:ff:
    f3:d1
prime1: 17667776196693030377 (0xf5308cd7cefd75e9)
prime2: 17596097080145549003 (0xf431e510f75d16cb)
exponent1: 10532946027144870681 (0x922c8a9b1254fb19)
exponent2: 7661660226727396529 (0x6a53af620bd344b1)
coefficient: 1528899226626897395 (0x1537bdbf047735f3)
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MGMCAQACEQDp4g/tVIkM50ygxVKPw4XDAgMBAAECEQC1vKjdpTudnr2AV7ay//PR
AgkA9TCM1879dekCCQD0MeUQ910WywIJAJIsipsSVPsZAghqU69iC9NEsQIIFTe9
vwR3NfM=
-----END RSA PRIVATE KEY-----

Если углубиться в это, похоже, проблема возникает в 64-битных системах, когда long все еще 32-битный.

https://github.com/openssl/openssl/blob/OpenSSL_1_0_2j/crypto/asn1/t_pkey.c#L82-L87:

if (BN_num_bytes(num) <= BN_BYTES) {
    if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg,
                   (unsigned long)num->d[0], neg,
                   (unsigned long)num->d[0])
        <= 0)
        return (0);

BN_BYTES равно 8 в системах, где SIXTY_FOUR_BIT_LONG или SIXTY_FOUR_BIT были определены во время настройки.

$ grep SIXTY_FOUR `locate opensslconf.h | grep ^/usr`
#define SIXTY_FOUR_BIT_LONG
#undef SIXTY_FOUR_BIT

Поскольку я SIXTY_FOUR_BIT_LONG, моя команда печати работает для 33 - до 64-битного диапазона.

$ uname -srmo
Linux 4.4.0-119-generic x86_64 GNU/Linux$ head -2 /etc/os-release
NAME="Ubuntu"
VERSION="16.04.4 LTS (Xenial Xerus)"
Bai Bing ответил: 28 марта 2018 в 04:47
Большое спасибо за ваш ответ! Похоже, что на Windows, долго 32 бит. Вот почему он отображает только нижние 32 бита.