У меня есть сообщение с ограничением размера 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, а затем выполнить те же шаги, как для шифрования:
- Кодирование сообщения
ApplyFunction
(с закрытым ключом) CalculateInverse
(с ключом publi c)
Но это не работает, поскольку pubKey
не имеет CalculateInverse
-метода. Итак, я попробовал странную вещь и теперь делаю следующее
- Кодируй сообщение
CalculateInverse
(с закрытым ключом) 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 */ }
Я сильно сомневаюсь, что это правильный способ сделать это. И почему я должен поменять местами экспоненты? Это все еще работает, даже если я не поменяю их местами.