Crypto ++ Raw RSA подписывает короткое сообщение коротким ключом - PullRequest
0 голосов
/ 27 февраля 2020

У меня есть сообщение с ограничением размера 128 бит, которое я хочу подписать и подтвердить, что я отправитель. У меня есть только одно требование: шифр не должен превышать 128-битный предел.

Итак, после некоторого исследования топологии c подписи и проверки я решил использовать Raw RSA с длиной ключа 128 бит, потому что я не нашел других подходящих алгоритмов, удовлетворяющих требованиям. Другие алгоритмы, кажется, всегда имеют какую-то нагрузку на память, которая требует, чтобы шифр был больше, но, возможно, я пропустил правильные (если так, было бы здорово дать мне подсказку), я знаю, что это можно взломать в кратчайшие сроки , но главное требование - короткое сообщение.

Итак, сначала я попытался зашифровать сообщение с помощью ключа publi c. Я хотел использовать схемы высокого уровня, которые предоставляет Crypto ++ (например, CryptoPP::RSAES_OAEP_SHA_Encryptor), но у них есть некоторый объем памяти для дайджестов и прочего, поэтому я использовал Raw RSA , чтобы выполнить вычисления напрямую , Мой код C ++ для en- / decryption выглядит следующим образом:

// This is our message
std::string message = "0123456789ABCDEX";
CryptoPP::Integer m((const byte *)message.data(), message.size());
std::cout << "message ( "<< std::dec << m.ByteCount() <<" bytes)   : " << std::hex << m << std::endl;

// Generate keys
Integer n("0x3a1a51415e596a0d3e261661a35a68f99");   // modulus
Integer e("0x11");                                  // public exponent
Integer d("0x15dfbe36ba1ba36848b5d3ad478bb011");    // private exponent

RSA::PrivateKey privKey;
RSA::PublicKey pubKey;

privKey.Initialize(n, e, d); // Used for decryption
pubKey.Initialize(n, e); // Used for encryption

// Encrypt
CryptoPP::Integer c = pubKey.ApplyFunction(m); //generate cipher
std::cout << "cipher  ( " << std::dec << c.ByteCount() << " bytes)   : " << std::hex << c << std::endl;

// Decrypt
CryptoPP::Integer r = privKey.CalculateInverse(prng, c);
std::cout << "decrypted ( " << std::dec <<r.ByteCount()<<" bytes) : " << std::hex << r << std::endl;

if (r == m)
{
    std::cout << "Decryption successful" << std::endl;
}
else
{
    std::cout << "Decryption failed" << std::endl;
}  

Вывод:

message ( 16 bytes)   : 30313233343536373839414243444558h
cipher  ( 16 bytes)   : 2e294ff384751724c7dbbc31def66511h
decrypted ( 16 bytes) : 30313233343536373839414243444558h
Decryption successful

Теперь, чтобы подписать мое сообщение, мне нужно использовать закрытый ключ для «шифрования». "и ключ publi c для" расшифровки "(я цитировал, поскольку технически это не шифрование). Под вышеупомянутой ссылкой есть также параграф о том, как выполнить шифрование закрытым ключом . Там написано, что нужно только переключить параметры e (publi c exponent) и d (private экспонента) при создании pubil c и private key, а затем выполнить те же шаги, как для шифрования:

  1. Кодирование сообщения
  2. ApplyFunction (с закрытым ключом)
  3. CalculateInverse (с ключом publi c)

Но это не работает, поскольку pubKey не имеет CalculateInverse -метода. Итак, я попробовал странную вещь и теперь делаю следующее

  1. Кодируй сообщение
  2. CalculateInverse (с закрытым ключом)
  3. ApplyFunction (с publi c key)

или в коде:

// This is our message
std::string message = "0123456789ABCDEX";
CryptoPP::Integer m((const byte *)message.data(), message.size());
std::cout << "message ( "<< std::dec << m.ByteCount() <<" bytes)   : " << std::hex << m << std::endl;

// Generate keys
Integer n("0x3a1a51415e596a0d3e261661a35a68f99");   // modulus
Integer e("0x11");                                  // now private exponent
Integer d("0x15dfbe36ba1ba36848b5d3ad478bb011");    // now public exponent

RSA::PrivateKey privKey;
RSA::PublicKey pubKey;

privKey.Initialize(n, d, e); // Used for signing (d and e are swapped)
pubKey.Initialize(n, d); // Used for verification

// Sign with the private key
CryptoPP::Integer c = privKey.CalculateInverse(prng, m); // 

std::cout << "cipher  ( " << std::dec << c.ByteCount() << " bytes)   : " << std::hex << c << std::endl;

// Verify with the public key
CryptoPP::Integer r = pubKey.ApplyFunction(c);

std::cout << "decrypted ( " << std::dec <<r.ByteCount()<<" bytes) : " << std::hex << r << std::endl;

if (r == m) { /* sucess */ } else { /* failed */ }

Я сильно сомневаюсь, что это правильный способ сделать это. И почему я должен поменять местами экспоненты? Это все еще работает, даже если я не поменяю их местами.

...