std::string avjackif::async_client_hello(boost::asio::yield_context yield_context) { proto::client_hello client_hello; client_hello.set_client("avim"); client_hello.set_version(0001); unsigned char to[512]; auto dh = DH_new(); DH_generate_parameters_ex(dh,64,DH_GENERATOR_5,NULL); DH_generate_key(dh); // 把 g,p, pubkey 传过去 client_hello.set_random_g((const void*)to, BN_bn2bin(dh->g, to)); client_hello.set_random_p((const void*)to, BN_bn2bin(dh->p, to)); client_hello.set_random_pub_key((const void*)to, BN_bn2bin(dh->pub_key, to)); auto tobesend = av_router::encode(client_hello); boost::asio::async_write(*m_sock, boost::asio::buffer(tobesend), yield_context); // 解码 std::unique_ptr<proto::server_hello> server_hello( (proto::server_hello*)async_read_protobuf_message(*m_sock, yield_context)); m_remote_addr.reset(new proto::av_address( av_address_from_string(server_hello->server_av_address()))); auto server_pubkey = BN_bin2bn((const unsigned char *) server_hello->random_pub_key().data(), server_hello->random_pub_key().length(), NULL); m_shared_key.resize(DH_size(dh)); // 密钥就算出来啦! DH_compute_key(&m_shared_key[0], server_pubkey, dh); BN_free(server_pubkey); std::printf("key = 0x"); for (int i=0; i<DH_size(dh); ++i) { std::printf("%x%x", (m_shared_key[i] >> 4) & 0xf, m_shared_key[i] & 0xf); } std::printf("\n"); DH_free(dh); return server_hello->random_pub_key(); }
bool avjackif::async_handshake(boost::asio::yield_context yield_context) { proto::client_hello client_hello; client_hello.set_client("avim"); client_hello.set_version(0001); unsigned char to[512]; auto dh = DH_new(); DH_generate_parameters_ex(dh,64,DH_GENERATOR_5,NULL); DH_generate_key(dh); // 把 g,p, pubkey 传过去 client_hello.set_random_g((const void*)to, BN_bn2bin(dh->g, to)); client_hello.set_random_p((const void*)to, BN_bn2bin(dh->p, to)); client_hello.set_random_pub_key((const void*)to, BN_bn2bin(dh->pub_key, to)); auto tobesend = av_router::encode(client_hello); boost::asio::async_write(*m_sock, boost::asio::buffer(tobesend), yield_context); std::uint32_t l; boost::asio::async_read(*m_sock, boost::asio::buffer(&l, sizeof(l)), boost::asio::transfer_exactly(4), yield_context); auto hostl = htonl(l); std::string buf; buf.resize(hostl + 4); memcpy(&buf[0], &l, 4); hostl = boost::asio::async_read(*m_sock, boost::asio::buffer(&buf[4], hostl), boost::asio::transfer_exactly(hostl), yield_context); // 解码 boost::scoped_ptr<proto::server_hello> server_hello((proto::server_hello*)av_router::decode(buf)); m_remote_addr.reset(new proto::avAddress( av_address_from_string(server_hello->server_av_address()))); auto server_pubkey = BN_bin2bn((const unsigned char *) server_hello->random_pub_key().data(), server_hello->random_pub_key().length(), NULL); m_shared_key.resize(DH_size(dh)); // 密钥就算出来啦! DH_compute_key(&m_shared_key[0], server_pubkey, dh); BN_free(server_pubkey); std::printf("key = 0x"); for (int i=0; i<DH_size(dh); ++i) { std::printf("%x%x", (m_shared_key[i] >> 4) & 0xf, m_shared_key[i] & 0xf); } std::printf("\n"); DH_free(dh); // 接着私钥加密 随机数 auto singned = RSA_private_encrypt(_rsa.get(), server_hello->random_pub_key()); proto::login login_packet; login_packet.set_user_cert( i2d_X509(_x509.get()) ); login_packet.set_encryped_radom_key(singned); boost::asio::async_write(*m_sock, boost::asio::buffer(av_router::encode(login_packet)), yield_context); // 读取回应 boost::asio::async_read(*m_sock, boost::asio::buffer(&l, sizeof(l)), boost::asio::transfer_exactly(hostl), yield_context); hostl = htonl(l); buf.resize(htonl(l) + 4); memcpy(&buf[0], &l, 4); boost::asio::async_read(*m_sock, boost::asio::buffer(&buf[4], htonl(l)), boost::asio::transfer_exactly(hostl), yield_context); // 解码 boost::scoped_ptr<proto::login_result> login_result((proto::login_result*)av_router::decode(buf)); return login_result.get()->result() == proto::login_result_login_result_code_LOGIN_SUCCEED; }
static void content_parse( const struct Banner1 *banner1, void *banner1_private, struct Banner1State *pstate, const unsigned char *px, size_t length, char *banner, unsigned *banner_offset, size_t banner_max) { struct SSLRECORD *ssl = &pstate->sub.ssl; unsigned state = ssl->record.state; unsigned remaining = ssl->record.remaining; unsigned i; enum { START, LENGTH0, LENGTH1, LENGTH2, CONTENTS, UNKNOWN, }; for (i=0; i<length; i++) switch (state) { case START: if (px[i] & 0x80) { state = UNKNOWN; break; } remaining = 0; ssl->record.type = px[i]; ssl->x.all.state = 0; DROPDOWN(i,length,state); case LENGTH0: remaining = px[i]; DROPDOWN(i,length,state); case LENGTH1: remaining <<= 8; remaining |= px[i]; DROPDOWN(i,length,state); case LENGTH2: remaining <<= 8; remaining |= px[i]; DROPDOWN(i,length,state); case CONTENTS: { unsigned len = (unsigned)length-i; if (len > remaining) len = remaining; switch (ssl->record.type) { case 0x02: /* server hello */ server_hello( banner1, banner1_private, pstate, px+i, len, banner, banner_offset, banner_max); break; case 0x0b: /* server certificate */ server_cert( banner1, banner1_private, pstate, px+i, len, banner, banner_offset, banner_max); break; } remaining -= len; i += len-1; if (remaining == 0) state = START; } break; case UNKNOWN: default: i = (unsigned)length; } ssl->record.state = state; ssl->record.remaining = remaining; }