Ключи Crypto++ и сжатые EC

Как я могу генерировать сжатые ключи ECDSA в Crypto++?

AutoSeededRandomPool prng;
ECDSA<ECP, SHA1>::PrivateKey privateKey;
ECDSA<ECP, SHA1>::PublicKey publicKey;
privateKey.Initialize( prng, CryptoPP::ASN1::secp256r1());

const Integer& x1 = privateKey.GetPrivateExponent();
cout << "priv:  " << std::hex << x1 << endl;
privateKey.MakePublicKey( publicKey );
const ECP::Point& q = publicKey.GetPublicElement();
const Integer& qx = q.x;
const Integer& qy = q.y;
cout << "pub x: " << std::hex << qx << endl;
cout << "pub y: " << std::hex << qy << endl;

Этот код генерирует пару ключей и печатает компоненты X и Y открытого ключа.

Мне нужно знать, есть ли способ распечатать компонент Y сжатого ключа, или мне нужно сгенерировать его из несжатого компонента y. Если мне нужно его сгенерировать, может кто-нибудь связать меня с хорошим объяснением того, как работать с классом Integer?

1 ответ

Решение

Как я могу создать сжатые ключи ECDSA в CryptoPP?

Вы не создаете сжатый ключ. Вы генерируете открытый ключ, а затем сжимаете его, если это то, что требуется. Из Как создать открытый ключ ECDSA с включенным сжатием точек? в группе пользователей Crpyto++:

ECDSA<ECP, SHA1>::Verifier verifier(...);
verifier.AccessKey().AccessGroupParameters().SetPointCompression(true); 

В вашем случае это будет:

publicKey.AccessGroupParameters().SetPointCompression(true);

поскольку verifier.AccessKey() возвращает открытый ключ ECDSA.


Мне нужно знать, есть ли способ распечатать компонент Y сжатого ключа

Сжатие - это опция формата презентации или оптимизации. Вы не можете напечатать компонент Y на сериализованном ключе со сжатием, потому что его там нет (см. Дампы ASN.1 ниже).

При включенном сжатии "сокращение" Y будет равно 1 или -1, в зависимости от знака компонента (знак указывает, в каком квадранте находится точка). Идея в том, что кто-то посылает вам пару {1,X} или пару {-1,X}, и вы можете решить для Y, потому что вы знаете, в каком квадранте он должен быть. Если Y допускается только быть положительным, вам нужно только сериализовать {X} (а не {-1,X} или {1,X}). (Я не углублялся в книги или стандарты, поэтому здесь могут быть некоторые ошибки).


... или если мне нужно сгенерировать его из несжатого компонента y. Если мне нужно его сгенерировать, может кто-нибудь связать меня с хорошим объяснением того, как работать с классом Integer?

Я понятия не имею, о чем ты говоришь здесь. Точка сжатия влияет на представление. Если вы включите сжатие точек и получите Y, вы все равно получите Y. Вы не можете вычислить сжатую точку. Вам нужны координаты X и Y.


Добавьте следующее в вашу программу:

publicKey.AccessGroupParameters().SetPointCompression(false);
ByteQueue q1;
publicKey.Save(q1);
cout << "Uncompressed size: " << dec << q1.MaxRetrievable() << endl;

publicKey.AccessGroupParameters().SetPointCompression(true);
ByteQueue q2;
publicKey.Save(q2);
cout << "Compressed size: " << dec << q2.MaxRetrievable() << endl;

Вот что я получил за вывод:

$ ./cryptopp-test.exe
priv:  4ce30d22d9593d9c7f4406eda1ce0740c7486106374d0abe7e352e1d5b1d5622h
pub x: 41a9bc936b6d1dd3a1ded997d7da08f1df990e9b50f9b58e9e4fd9319758ea34h
pub y: 4ad39ffb79c402063a99ecbc0cac8fde606db6764ace90933feee5f8d65937a2h
Uncompressed size: 311
Compressed size: 246

Если вы получите Y после включения точечного сжатия, вы все равно получите 4ad39ffb79c402063a99ecbc0cac8fde606db6764ace90933feee5f8d65937a2h, потому что сжатие влияет на представление.


Теперь добавьте следующее, чтобы выгрузить несжатый и сжатый ключ:

FileSink fs1("key-1.der", true);
q1.TransferTo(fs1);

FileSink fs2("key-2.der", true);
q2.TransferTo(fs2);

Ключи выгружаются в кодировке DER в ASN.1 и соответствуют SEC 1: криптографии с эллиптическими кривыми (и в меньшей степени ANSI 9.62 и RFC 5480, формат ECC SubjectPublicKeyInfo) - см. Ниже об элементах поля OCTET STRING против BIT STRING).

Вы можете запустить Питера Гутмана dumpasn1 на них:

$ dumpasn1.exe key-1.der 
  0 307: SEQUENCE {
  4 236:   SEQUENCE {
  7   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
 16 224:     SEQUENCE {
 19   1:       INTEGER 1
 22  44:       SEQUENCE {
 24   7:         OBJECT IDENTIFIER prime-field (1 2 840 10045 1 1)
 33  33:         INTEGER
       :           00 FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00
       :           00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF
       :           FF
       :         }
 68  68:       SEQUENCE {
 70  32:         OCTET STRING
       :           FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00 00
       :           00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FC
104  32:         OCTET STRING
       :           5A C6 35 D8 AA 3A 93 E7 B3 EB BD 55 76 98 86 BC
       :           65 1D 06 B0 CC 53 B0 F6 3B CE 3C 3E 27 D2 60 4B
       :         }
138  65:       OCTET STRING
       :         04 6B 17 D1 F2 E1 2C 42 47 F8 BC E6 E5 63 A4 40
       :         F2 77 03 7D 81 2D EB 33 A0 F4 A1 39 45 D8 98 C2
       :         96 4F E3 42 E2 FE 1A 7F 9B 8E E7 EB 4A 7C 0F 9E
       :         16 2B CE 33 57 6B 31 5E CE CB B6 40 68 37 BF 51
       :         F5
205  33:       INTEGER
       :         00 FF FF FF FF 00 00 00 00 FF FF FF FF FF FF FF
       :         FF BC E6 FA AD A7 17 9E 84 F3 B9 CA C2 FC 63 25
       :         51
240   1:       INTEGER 1
       :       }
       :     }
243  66:   BIT STRING
       :     04 41 A9 BC 93 6B 6D 1D D3 A1 DE D9 97 D7 DA 08
       :     F1 DF 99 0E 9B 50 F9 B5 8E 9E 4F D9 31 97 58 EA
       :     34 4A D3 9F FB 79 C4 02 06 3A 99 EC BC 0C AC 8F
       :     DE 60 6D B6 76 4A CE 90 93 3F EE E5 F8 D6 59 37
       :     A2
       :   }

$ dumpasn1.exe key-2.der 
  0 243: SEQUENCE {
  3 204:   SEQUENCE {
  6   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
 15 192:     SEQUENCE {
 18   1:       INTEGER 1
 21  44:       SEQUENCE {
 23   7:         OBJECT IDENTIFIER prime-field (1 2 840 10045 1 1)
 32  33:         INTEGER
       :           00 FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00
       :           00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF
       :           FF
       :         }
 67  68:       SEQUENCE {
 69  32:         OCTET STRING
       :           FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00 00
       :           00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FC
103  32:         OCTET STRING
       :           5A C6 35 D8 AA 3A 93 E7 B3 EB BD 55 76 98 86 BC
       :           65 1D 06 B0 CC 53 B0 F6 3B CE 3C 3E 27 D2 60 4B
       :         }
137  33:       OCTET STRING
       :         03 6B 17 D1 F2 E1 2C 42 47 F8 BC E6 E5 63 A4 40
       :         F2 77 03 7D 81 2D EB 33 A0 F4 A1 39 45 D8 98 C2
       :         96
172  33:       INTEGER
       :         00 FF FF FF FF 00 00 00 00 FF FF FF FF FF FF FF
       :         FF BC E6 FA AD A7 17 9E 84 F3 B9 CA C2 FC 63 25
       :         51
207   1:       INTEGER 1
       :       }
       :     }
210  34:   BIT STRING
       :     02 41 A9 BC 93 6B 6D 1D D3 A1 DE D9 97 D7 DA 08
       :     F1 DF 99 0E 9B 50 F9 B5 8E 9E 4F D9 31 97 58 EA
       :     34
       :   }

Обратите внимание на различия:

# key-1.der
243  66:   BIT STRING
       :     04 41 A9 BC 93 6B 6D 1D D3 A1 DE D9 97 D7 DA 08
       :     F1 DF 99 0E 9B 50 F9 B5 8E 9E 4F D9 31 97 58 EA
       :     34 4A D3 9F FB 79 C4 02 06 3A 99 EC BC 0C AC 8F
       :     DE 60 6D B6 76 4A CE 90 93 3F EE E5 F8 D6 59 37
       :     A2

против:

# key-2.der
210  34:   BIT STRING
       :     02 41 A9 BC 93 6B 6D 1D D3 A1 DE D9 97 D7 DA 08
       :     F1 DF 99 0E 9B 50 F9 B5 8E 9E 4F D9 31 97 58 EA
       :     34
       :   }

В первом кодируются два целых числа, а во втором - одно целое число. Общая ценность 41 A9 BC 93 ... 97 58 EA 34 и это твое pub x выше. Недостающая строка из ключа-2 4A D3 9F FB ... D6 59 37 A2 и это pub y выше. Для полноты значения кодируются как {X,Y} или {X}, а не как кодировка целых чисел в ASN.1.

Последнее различие - первый октет BIT STRING: 02 против 04 (или 03). 04 указывает на несжатую точку. Из RFC 5480, раздел 2.2:

    The first octet of the OCTET STRING indicates whether the key is
    compressed or uncompressed.  The uncompressed form is indicated
    by 0x04 and the compressed form is indicated by either 0x02 or
    0x03 (see 2.3.3 in [SEC1]).  The public key MUST be rejected if
    any other value is included in the first octet.

И после просмотра стандарта и раздела 2.2, в Crypto++ может быть ошибка: BIT STRING, но стандарт четко обсуждает OCTET STRING,

РЕДАКТИРОВАТЬ 1: Кажется, это ошибка Crypto++ под ANSI 9.62, тоже. Раздел 6.2, Синтаксис для конечных элементов поля и точек эллиптической кривой (стр. 20)

    A finite field element shall be represented by a value of type FieldElement:
      FieldElement ::= OCTET STRING
    The value of FieldElement shall be the octet string representation of a field
    elementfollowing the conversion routine in Section 4.3.1.
    An elliptic curve point shall be represented by a value of type ECPoint:
      ECPoint ::= OCTET STRING

РЕДАКТИРОВАТЬ 2: Crypto++ использует формат, указанный в SEC 1: Криптография по эллиптической кривой. Приложение C (страница 77) гласит:

    Finally, a specific field element is represented by the following type
      FieldElement ::= OCTET STRING
    whose value is the octet string obtained from the conversion routines
    given in Section 2.3.5.
Другие вопросы по тегам