Создание RSA PublicKey из байтов с помощью Crypto ++ - PullRequest
0 голосов
/ 03 августа 2020

Вчера я установил сервер Go, который генерирует ключ RSA и затем отправляет его моему клиенту C ++ в форме PKCS#1, ASN.1 DER. (https://godoc.org/crypto/x509#MarshalPKCS1PublicKey)

Сегодня я перепробовал кучу вещей, но ни один из них не подошел. После того, как я наконец смог, возможно, получить байты в BufferedTransformation для использования PEM_Load, я закодировал байты в Base64 и вручную добавил текст верхнего и нижнего колонтитула. Затем я столкнулся с «ошибкой декодирования BER», и теперь я застрял и не уверен, что то, что я создал, даже действительный ключ.

и вот полный код:

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include <cryptopp/pem.h>
#include <cryptopp/rsa.h>
#include <cryptopp/osrng.h>
#include <cryptopp/base64.h>
#include <cryptopp/dsa.h>

using boost::asio::ip::tcp;
using namespace CryptoPP;

enum { max_length = 1024 };

int main( int argc, char* argv[] ) {
    RSA::PrivateKey rsa_private;
    AutoSeededRandomPool random;

    rsa_private.GenerateRandomWithKeySize( random, 2048 );
    auto rsa_public = RSA::PublicKey( rsa_private );

    try {
        boost::asio::io_context io_context;

        tcp::socket s( io_context );
        tcp::resolver resolver( io_context );
        boost::asio::connect( s, resolver.resolve( "127.0.0.1", "9999" ));

        int headersize;
        size_t reply_length = boost::asio::read( s,
            boost::asio::buffer( &headersize, sizeof(headersize ) ) );

        printf( "Got header with size %i\n", headersize );

        std::vector<CryptoPP::byte> RSA_PUB(headersize);
        size_t read_size = boost::asio::read( s,
            boost::asio::buffer( RSA_PUB.data(), headersize ) );
        RSA::PublicKey testpub;

        Base64Encoder encoder;
        encoder.Put( RSA_PUB.data( ), RSA_PUB.size( ) );
        encoder.MessageEnd( );

        std::string encoded;
        auto encoded_size = encoder.MaxRetrievable( );
        if ( encoded_size ) {
            encoded.resize( encoded_size );
            encoder.Get( ( byte* )&encoded[ 0 ], encoded.size( ) );
        }

        encoded.insert( 0, "-----BEGIN PUBLIC KEY-----\n" );
        encoded.append( "-----END PUBLIC KEY-----" );

        
        //ArraySource( RSA_PUB.data( ), RSA_PUB.size( ), true );
        CryptoPP::ByteQueue test;
        test.Put( (byte*)encoded.data( ), encoded.size( ) );
        test.MessageEnd( );

        
        PEM_Load( test, testpub );
        //std::cout.write( RSA_PUB.data( ), RSA_PUB.size( ) );

    } catch ( std::exception& e ) {
        std::cerr << "Exception: " << e.what( ) << "\n";
    }
    std::cin.get( );
    return 0;
}

Обновление: сегодня я пошел дальше и сохранил сгенерированный ключ в файл из Crypto ++, затем сохранил ключ, сгенерированный из Go, и сравнил их: Изображение и на его основе я вижу, что формат очень похож, так что я, по крайней мере, не так уж и далек. Мой следующий шаг - найти и использовать программное обеспечение для проверки формата, поскольку я видел, что он упоминался в прошлом.

Обновление 2: Совершенно очевидно, что MarshalPKCS1PublicKey не учитывает то, что я бы назвал заголовок из данных и сразу переходит к фактическому значению. Не знаю, как это решить. Спрашивать в разладе Go.

1 Ответ

0 голосов
/ 19 августа 2020

Загрузка ключа с использованием BERDecodePublicKey из PublicKey сработала! То, как я пытался его загрузить, ожидало полного формата X.509. Чтобы получить байты Crypto ++ в том же формате, я бы использовал DEREncodePublicKey.

...