Отправка PublicKey внутри пакета

Для академического сетевого приложения я хотел бы настроить обмен ключами RSA между двумя виртуальными машинами. Я использую Crypto ++ для генерации RSA::PublicKeyи теперь я должен отправить его в пользовательском кадре уровня 2 (пакет будет создан с libcrafter).

Дело в том, что я понятия не имею, как написать ключ в сети, например, получатель, нюхая пакет, может каким-то образом восстановить RSA::PublicKey,

Я пытался сохранить это сырье в строку, но как говорится Вот, PublicKey класс содержит другие данные, затем просто необработанный ключ (данные, которые мне не нужны). тем не менее, мне это удается, но на ресепшене я не могу просто перестроить PublicKey …

Можно ли каким-то образом объединить модуль, простые числа и открытый показатель, чтобы восстановить publicKey на приеме?

отправитель

Вот код, который я использую у отправителя. Это важные строки, но у моей программы есть другая функциональность, и было бы слишком долго размещать ее целиком здесь).

AutoSeededRandomPool rng;
RSA::PrivateKey privateKey;
privateKey.GenerateRandomWithKeySize(rng, 3072);
RSA::PublicKey publicKey(privateKey);
cout << ">> Key generated" <<endl;

/* Convert key to string then to const char* */
std::string publicKeyString;
publicKey.BEREncode( StringSink(publicKeyString).Ref() );

const char * publicKeyChar = publicKeyString.c_str();
cout <<"key size : "<<publicKeyString.size()<< endl;

/* Send Packet */
Crafter::RawLayer type1("K");
Crafter::RawLayer key_send(publicKeyChar);
//Crafter::RawLayer key_send(publicKeyString.c_str(), publicKeyString.length());
Crafter::Packet packet_key (ether_header / type1 / key_send);
packet_key.Send(iface);

Получатель

И вот моя попытка восстановить ключ.

/* Extract Payload */
PayloadLayer *payload_rcv = pack_recu.getLayerOfType<PayloadLayer>();
size_t payload_size  = payload_rcv->getPayloadLen() ;
Crafter::byte *payload = payload_rcv->getPayload();

cout << ">> Public Key recieved"<<endl;

// Convert into RSA::PublicKey
stringstream ss;
for (int i=0; i< payload_size; i++)
ss << payload[i];
string payload_string = ss.str();
cout << "Payload Size: "<<payload_size<<endl;
cin.get();
StringSource stringSource(payload_string, true);
RSA::PublicKey publicKey2;
publicKey2.BERDecode(stringSource);

data->publicKey = publicKey2;

И вот результат запуска программы:

terminate called after throwing an instance of 'CryptoPP::BERDecodeErr'
what():  BER decode error

Я уверен, что ошибка исходит от преобразования из строки в publicKey... BERDecode функция войны изначально думала восстановить ключ из файла

У кого-нибудь есть решение? Я думаю, что отправление всех элементов для восстановления ключа может быть лучше, но я не могу понять, как это сделать …

3

Решение

publicKey.BEREncode (StringSink (publicKeyString) .Ref ());

const char * publicKeyChar = publicKeyString.c_str ();

Кодировка BER, вероятно, имеет встроенный NULL, поэтому вы не можете использовать обычные операции C-строки над ним:

const char * publicKeyChar = publicKeyString.c_str();
...
Crafter::RawLayer key_send(publicKeyChar);

При написании закодированного открытого ключа следующее выглядит корректно. Вы должны раскомментировать и использовать его (я использую data а также size потому что он логически отделяется от C-строк и длины).

Crafter::RawLayer key_send(publicKeyString.data(), publicKeyString.size());

Так что весь Crypto ++ может выглядеть следующим образом:

// Host's private key, generate or Load() it...
RSA::PrivateKey privKey;
...

// Create a public key from the private key
RSA::PublicKey pubKey(privKey);

// Temporaries
string spki;
StringSink ss(spki);

// Use Save to DER encode the Subject Public Key Info (SPKI)
pubKey.Save(ss);

Crafter::RawLayer key_send(spki.data(), spki.size());

Затем, чтобы восстановить его:

// Key payload
const PayloadLayer& payload_rcv = *pack_recu.getLayerOfType<PayloadLayer>();

// Get a contiguous array (I don't know what this is called in Crafter)
payload_rcv.PullUp();

// Use the array directly to avoid the copy
ArraySource as(payload_rcv.data(), payload_rcv.size(), true /*pumpAll*/);
RSA::PublicKey pubKey;

// Use Load to BER decode the Subject Public Key Info (SPKI)
pubKey.Load(as);

// Validate it before using it
AutoSeededRandomPool prng;
pubKey.ThrowIfInvalid(prng);

Я думаю, что важно использовать Subject Public Key Info (SPKI), а не просто Открытый ключ. SPKI включает в себя идентификатор алгоритма посредством OID. Это сделает алгоритм немного проще в дальнейшем. Позже вы можете переключиться на ключ ECDSA или ключ ed25519, и этот тип ключа будет частью полезной нагрузки ключа.


terminate called after throwing an instance of 'CryptoPP::BERDecodeErr'
what():  BER decode error

Очевидно, вы должны создать try/catchи поймать BERDecodeErr:

try
{
// Use Load to BER decode the Subject Public Key Info (SPKI)
pubKey.Load(as);

// Validate it before using it
AutoSeededRandomPool prng;
pubKey.ThrowIfInvalid(prng);
}
catch(const BERDecodeErr& ex)
{
cerr << ex.what() << endl;
}
catch(const InvalidMaterial& ex)
{
cerr << ex.what() << endl;
}

А вот как выглядит информация об открытом ключе субъекта:

$ cat cryptopp-test.cpp
...
int main(int argc, char* argv[])
{
AutoSeededRandomPool prng;

RSA::PrivateKey rsaPrivate;
rsaPrivate.GenerateRandomWithKeySize(prng, 3072);

RSA::PublicKey rsaPublic(rsaPrivate);
FileSink sink("rsa-public.der");
rsaPublic.Save(sink);

return 0;
}

А потом использовать что-то вроде Питера Гутмана dumpasn1:

$ dumpasn1 rsa-public.der
0 416: SEQUENCE {
4  13:   SEQUENCE {
6   9:     OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
17   0:     NULL
:     }
19 397:   BIT STRING, encapsulates {
24 392:     SEQUENCE {
28 385:       INTEGER
:         00 CE B0 19 0D 0C EB 87 BD 6B 51 6C BB 00 9C EE
:         1D 75 9C 28 DC 0E 8E 88 9A 95 8A 3B 6C BD 1F 3F
:         03 05 22 8E 3D 19 33 D7 C5 A3 28 4F 13 3D 9E BF
:         5A 54 51 AE D6 DA C3 AC 1D 9C 4C A3 47 C0 04 8F
:         9D 0A DD 38 60 56 E3 9C DB 7C EA A8 3F 52 93 99
:         40 90 14 41 0A 3B 58 F2 13 9F 38 64 18 DD 62 55
:         D2 32 53 A0 D5 1A 54 E7 8D 23 01 E0 97 ED F9 C7
:         68 9F E2 00 48 99 53 40 6E 7E 5C DA 47 39 4A 41
:                 [ Another 257 bytes skipped ]
417   1:       INTEGER 17
:       }
:     }
:   }

0 warnings, 0 errors.
3

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector