diff --git a/quic_lfl.cpp b/quic_lfl.cpp new file mode 100644 index 0000000..cef8081 --- /dev/null +++ b/quic_lfl.cpp @@ -0,0 +1,848 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QUIC_AES_128_KEY_LEN 16 +#define QUIC_IV_LEN 12 +#define QUIC_MAX_UDP_PAYLOAD_SIZE 65527 + +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// +// 获取没有加密的QUIC包 +/////////////////////////////////////////////////////////////////////////////// + +using namespace std; +void printByteStream(const vector &byteStream) +{ + for (const auto &byte : byteStream) + { + cout << hex << setw(2) << setfill('0') << static_cast(byte) << " "; + } + cout << endl << endl; +} +vector getAckFrame() +{ + return {0x02, 0x00, 0x00, 0x00, 0x00}; +} +vector concatenateByteStreams(const vector> &byteStreams) +{ + // 连接vector,这个方法虽然可以复用,但是看着起来不直观 + vector result; + for (const auto &byteStream : byteStreams) + { + result.insert(result.end(), byteStream.begin(), byteStream.end()); + } + return result; +} +vector getLenBytes(const size_t length, int return_len) +{ + // return_len为0表示变长,其余值为指定长度 + // 输入一个字节流数据,返回它的长度,用字节流表示 + if (return_len == 0) + { // 变长 + if (length < 64) + { + return {static_cast(length)}; + } + else if (length < 16383) + { + unsigned short len = length | 0x4000; + return {static_cast((len >> 8) & 0xFF), static_cast(len & 0xFF)}; + } + else if (length < 1073741823) + { + unsigned int len = length | 0x40000000; + return { + static_cast((len >> 24) & 0xFF), + static_cast((len >> 16) & 0xFF), + static_cast((len >> 8) & 0xFF), + static_cast(len & 0xFF)}; + } + else + { + unsigned long long len = length | 0x4000000000000000; + return { + static_cast((len >> 56) & 0xFF), + static_cast((len >> 48) & 0xFF), + static_cast((len >> 40) & 0xFF), + static_cast((len >> 32) & 0xFF), + static_cast((len >> 24) & 0xFF), + static_cast((len >> 16) & 0xFF), + static_cast((len >> 8) & 0xFF), + static_cast(len & 0xFF)}; + } + } + else + { + vector lengthBytes; + for (int i = return_len - 1; i >= 0; i--) + { + lengthBytes.push_back(static_cast((length >> (8 * i)) & 0xFF)); + } + return lengthBytes; + } +} +vector buildHeader(const size_t plain_header_len, const vector &dcid, const vector &scid) +{ + // unsigned char packet_type_bit = 0b1; // Record Type: Handshake + // unsigned char fix_bit = 0b1; + // unsigned char long_packet_type = 0b00; + // unsigned char keep_bit = 0b00; // 受头部包含 + // unsigned char packet_number_length_bit = 0b01; // 受头部保护,真实长度=该值+1 + // 上面几个字段 一起组成field + vector field = {0xc1}; // c1: 11000001; cf: 11001111; c3: + vector version = {0x00, 0x00, 0x00, 0x01}; // QUIC Protocol Version + vector destination_cid_length = getLenBytes(dcid.size(), 0); // 变长 + vector destination_cid = dcid; + vector source_cid_length = getLenBytes(scid.size(), 0); // 变长 + vector source_cid = scid; + vector token_length = {0x00}; + vector token = {}; + vector packet_number = {0x00, 0x01}; + + // 计算length包括packetnumber,payload + size_t packet_number_payload_len = packet_number.size()+plain_header_len+16; // 长度包括包号的长度,加密后的长度(加密前的长度+认证标签16) + vector length = getLenBytes(packet_number_payload_len, 0); // 变长变量,数据包剩余部分(也就是数据包号字段和载荷字段)的字节长度 + + // 构建QUIC数据包的字节流 + vector> byteStreams = {field, version, destination_cid_length, destination_cid, source_cid_length, source_cid, token_length, token, length, packet_number}; + vector header = concatenateByteStreams(byteStreams); + + return header; +} +vector keyShareExtension() +{ + vector type = {0x00, 0x33}; // key_share + vector length; // 下面动态赋值 + + vector key_share = {0x00, 0x1d, 0x00, 0x20, 0x9d, 0x3c, 0x94, 0x0d, 0x89, 0x69, 0x0b, 0x84, 0xd0, + 0x8a, 0x60, 0x99, 0x3c, 0x14, 0x4e, 0xca, 0x68, 0x4d, 0x10, 0x81, 0x28, + 0x7c, 0x83, 0x4d, 0x53, 0x11, 0xbc, 0xf3, 0x2b, 0xb9, 0xda, 0x1a}; + + length = getLenBytes(key_share.size(), 2); + + vector> helf_key_share_extension_datas = {type, length, key_share}; + vector helf_key_share_extension_data = concatenateByteStreams(helf_key_share_extension_datas); + return helf_key_share_extension_data; +} +vector supportedVersionExtension() +{ + vector type = {0x00, 0x2b}; + vector length; // 下面动态赋值 bytes.fromhex('0002') + vector supported_version = {0x03, 0x04}; + length = getLenBytes(supported_version.size(), 2); + vector> helf_supported_version_extension_datas = {type, length, supported_version}; + vector helf_supported_version_extension_data = concatenateByteStreams(helf_supported_version_extension_datas); + return helf_supported_version_extension_data; +} +vector getServerHello() +{ + vector type = {0x02}; // serverhello + vector length; // 下面动态赋值 + vector version = {0x03, 0x03}; // TLS1.2 + vector random = {0xee, 0xfc, 0xe7, 0xf7, 0xb3, 0x7b, 0xa1, 0xd1, 0x63, 0x2e, 0x96, 0x67, + 0x78, 0x25, 0xdd, 0xf7, 0x39, 0x88, 0xcf, 0xc7, 0x98, 0x25, 0xdf, 0x56, + 0x6d, 0xc5, 0x43, 0x0b, 0x9a, 0x04, 0x5a, 0x12}; + vector session_id_length = {0x00}; + vector cipher_suite = {0x13, 0x01}; + vector compression_method = {0x00}; + vector compression_length = {0x00, 0x2e}; + + vector extension_key_share = keyShareExtension(); + vector extension_supported_version = supportedVersionExtension(); + vector> helf_crypto_datas = {version, random, session_id_length, cipher_suite, + compression_method, compression_length, extension_key_share, extension_supported_version}; + vector helf_crypto_data = concatenateByteStreams(helf_crypto_datas); + + length = getLenBytes(helf_crypto_data.size(), 3); + + vector> byteStreams = {type, length, helf_crypto_data}; + vector server_hello = concatenateByteStreams(byteStreams); + return server_hello; +} + +vector getCryptoFrame() +{ + vector frame_type = {0x06}; // 0x06 + vector offset = {0x00}; + + vector crypto_data = getServerHello(); // 假设有 serverHello() 函数返回加密数据 + + vector length = getLenBytes(crypto_data.size(), 0); + + vector crypto_frame; + crypto_frame.insert(crypto_frame.end(), frame_type.begin(), frame_type.end()); + crypto_frame.insert(crypto_frame.end(), offset.begin(), offset.end()); + crypto_frame.insert(crypto_frame.end(), length.begin(), length.end()); + crypto_frame.insert(crypto_frame.end(), crypto_data.begin(), crypto_data.end()); + + return crypto_frame; +} +vector> getIntialPlainQuic(const vector &dcid, const vector &scid) +{ + vector ack_frame = getAckFrame(); + vector crypto_frame = getCryptoFrame(); + + vector plain_payload; + plain_payload.insert(plain_payload.end(), ack_frame.begin(), ack_frame.end()); + plain_payload.insert(plain_payload.end(), crypto_frame.begin(), crypto_frame.end()); + + vector header = buildHeader(plain_payload.size(), dcid, scid); // 假设有 buildHeader 函数构建头部信息 + + vector> header_plain_payload; + header_plain_payload.push_back(header); + header_plain_payload.push_back(plain_payload); + + return header_plain_payload; // 返回header,plain_payload +} +vector> getHandshakePlainQuic(const vector &dcid, const vector &scid) +{ + // uint8_t header_form = 0b1; // Record Type: Handshake + // uint8_t fix_bit = 0b1; + // uint8_t packet_type = 0b10; // handshake + vector field = {0xee}; // 后面4位随机 + vector version = {0x00, 0x00, 0x00, 0x01}; // QUIC Protocol Version + vector destination_cid_length = getLenBytes(dcid.size(), 0); // 变长 + vector destination_cid = dcid; + vector source_cid_length = getLenBytes(scid.size(), 0); // 变长 + vector source_cid = scid; + vector plain_payload = getAckFrame(); // 内容不重要,客户端可能解密不了,待测试 + vector length = getLenBytes(plain_payload.size(), 0); + vector packet_number = {0x00}; // 首个为0 + + vector header; + header.insert(header.end(), field.begin(), field.end()); + header.insert(header.end(), version.begin(), version.end()); + header.insert(header.end(), destination_cid_length.begin(), destination_cid_length.end()); + header.insert(header.end(), destination_cid.begin(), destination_cid.end()); + header.insert(header.end(), source_cid_length.begin(), source_cid_length.end()); + header.insert(header.end(), source_cid.begin(), source_cid.end()); + header.insert(header.end(), length.begin(), length.end()); + header.insert(header.end(), packet_number.begin(), packet_number.end()); + + + vector> header_plain_payload; + header_plain_payload.push_back(header); + header_plain_payload.push_back(plain_payload); + + return header_plain_payload; // 返回header,plain_payload +} + +/////////////////////////////////////////////////////////////////////////////// +// 获取初始密钥和key,iv,hp +/////////////////////////////////////////////////////////////////////////////// +typedef struct +{ + size_t len; + u_char *data; +} quic_str_t; +typedef struct quic_secret_s +{ + quic_str_t secret; + quic_str_t key; + quic_str_t iv; + quic_str_t hp; +} quic_secret_t; +#define quic_string(str) \ + { \ + sizeof(str) - 1, (u_char *)str \ + } +static void quic_str_to_hex(const char *message, u_char *data, size_t len) +{ + cout<> 8) == 0xff0000) + return (uint8_t)version; + + // Facebook mvfst, based on draft -22. + if (version == 0xfaceb001) + return 22; + + // Facebook mvfst, based on draft -27. + if (version == 0xfaceb002 || version == 0xfaceb00e) + return 27; + + // GQUIC Q050, T050 and T051: they are not really based on any drafts, + // but we must return a sensible value + if (version == 0x51303530 || version == 0x54303530 || version == 0x54303531) + return 27; + + /* + * https://tools.ietf.org/html/draft-ietf-quic-transport-32#section-15 + * "Versions that follow the pattern 0x?a?a?a?a are reserved for use in + * forcing version negotiation to be exercised" + * It is tricky to return a correct draft version: such number is primarly + * used to select a proper salt (which depends on the version itself), but + * we don't have a real version here! Let's hope that we need to handle + * only latest drafts... + */ + if ((version & 0x0F0F0F0F) == 0x0a0a0a0a) + return 29; + + return 0; +} +static inline uint8_t quic_draft_is_max(uint32_t version, uint8_t max_version) +{ + uint8_t draft_version = quic_draft_version(version); + return draft_version && draft_version <= max_version; +} +void LOG(const std::string &message) +{ + std::cerr << "[LOG] " << message << std::endl; +} +static int hkdf_expand(quic_str_t *out, const EVP_MD *digest, const quic_str_t *prk, const quic_str_t *info) +{ + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + if (pctx == NULL) + { + LOG("EVP_PKEY_CTX_new_id() failed"); + return -1; + } + + if (EVP_PKEY_derive_init(pctx) <= 0) + { + LOG("EVP_PKEY_derive_init() failed"); + goto failed; + } + + if (EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) <= 0) + { + LOG("EVP_PKEY_CTX_hkdf_mode() failed"); + goto failed; + } + + if (EVP_PKEY_CTX_set_hkdf_md(pctx, digest) <= 0) + { + LOG("EVP_PKEY_CTX_set_hkdf_md() failed"); + goto failed; + } + + if (EVP_PKEY_CTX_set1_hkdf_key(pctx, prk->data, prk->len) <= 0) + { + LOG("EVP_PKEY_CTX_set1_hkdf_key() failed"); + goto failed; + } + + if (EVP_PKEY_CTX_add1_hkdf_info(pctx, info->data, info->len) <= 0) + { + LOG("EVP_PKEY_CTX_add1_hkdf_info() failed"); + goto failed; + } + if (EVP_PKEY_derive(pctx, out->data, &(out->len)) <= 0) + { + LOG("EVP_PKEY_derive() failed"); + goto failed; + } + + EVP_PKEY_CTX_free(pctx); + return 0; + +failed: + + EVP_PKEY_CTX_free(pctx); + return -1; +} +static int quic_hkdf_expand(const EVP_MD *digest, quic_str_t *out, const quic_str_t *label, const quic_str_t *prk) +{ + + uint8_t info_buf[20]; + info_buf[0] = 0; + info_buf[1] = out->len; + info_buf[2] = label->len; + + uint8_t *p = (u_char *)memcpy(&info_buf[3], label->data, label->len) + label->len; + *p = '\0'; + + quic_str_t info; + info.len = 2 + 1 + label->len + 1; + info.data = info_buf; + // printf("%zu",info.len); + // LOG("info:"); + // quic_str_to_hex("info:",info.data,info.len); + + if (hkdf_expand(out, digest, prk, &info) != 0) + { + return -1; + } + + return 0; +} +static int hkdf_extract(quic_str_t *out, const EVP_MD *digest, const quic_str_t *secret, const quic_str_t *initial_salt) +{ + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + if (pctx == NULL) + { + LOG("EVP_PKEY_CTX_new_id() failed"); + return -1; + } + + if (EVP_PKEY_derive_init(pctx) <= 0) + { + LOG("EVP_PKEY_derive_init() failed"); + goto failed; + } + + if (EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) <= 0) + { + LOG("EVP_PKEY_CTX_hkdf_mode() failed"); + goto failed; + } + + if (EVP_PKEY_CTX_set_hkdf_md(pctx, digest) <= 0) + { + LOG("EVP_PKEY_CTX_set_hkdf_md() failed"); + goto failed; + } + + if (EVP_PKEY_CTX_set1_hkdf_key(pctx, secret->data, secret->len) <= 0) + { + LOG("EVP_PKEY_CTX_set1_hkdf_key() failed"); + goto failed; + } + + if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, initial_salt->data, initial_salt->len) <= 0) + { + LOG("EVP_PKEY_CTX_set1_hkdf_salt() failed"); + goto failed; + } + + if (EVP_PKEY_derive(pctx, out->data, &(out->len)) <= 0) + { + LOG("EVP_PKEY_derive() failed"); + goto failed; + } + + EVP_PKEY_CTX_free(pctx); + return 0; + +failed: + + EVP_PKEY_CTX_free(pctx); + return -1; +} +static int quic_keys_set_initial_secret(quic_secret_t *server_secret, const quic_str_t *dcid, uint32_t version) +{ + unsigned int i; + const quic_str_t initial_salt_v1 = quic_string( + "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a"); + const quic_str_t initial_salt_draft_22 = quic_string( + "\x7f\xbc\xdb\x0e\x7c\x66\xbb\xe9\x19\x3a\x96\xcd\x21\x51\x9e\xbd\x7a\x02\x64\x4a"); + const quic_str_t initial_salt_draft_23 = quic_string( + "\xc3\xee\xf7\x12\xc7\x2e\xbb\x5a\x11\xa7\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02"); + const quic_str_t initial_salt_draft_29 = quic_string( + "\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97\x86\xf1\x9c\x61\x11\xe0\x43\x90\xa8\x99"); + const quic_str_t initial_salt_draft_q50 = quic_string( + "\x50\x45\x74\xEF\xD0\x66\xFE\x2F\x9D\x94\x5C\xFC\xDB\xD3\xA7\xF0\xD3\xB5\x6B\x45"); + const quic_str_t initial_salt_draft_t50 = quic_string( + "\x7f\xf5\x79\xe5\xac\xd0\x72\x91\x55\x80\x30\x4c\x43\xa2\x36\x7c\x60\x48\x83\x10"); + const quic_str_t initial_salt_draft_t51 = quic_string( + "\x7a\x4e\xde\xf4\xe7\xcc\xee\x5f\xa4\x50\x6c\x19\x12\x4f\xc8\xcc\xda\x6e\x03\x3d"); + + const quic_str_t *initial_salt; + if (version == 0x51303530) + { + initial_salt = &initial_salt_draft_q50; + } + else if (version == 0x54303530) + { + initial_salt = &initial_salt_draft_t50; + } + else if (version == 0x54303531) + { + initial_salt = &initial_salt_draft_t51; + } + else if (quic_draft_is_max(version, 22)) + { + initial_salt = &initial_salt_draft_22; + } + else if (quic_draft_is_max(version, 28)) + { + initial_salt = &initial_salt_draft_23; + } + else if (quic_draft_is_max(version, 32)) + { + initial_salt = &initial_salt_draft_29; + } + else + { + initial_salt = &initial_salt_v1; + } + + /* + * RFC 9001, section 5. Packet Protection + * + * Initial packets use AEAD_AES_128_GCM. The hash function + * for HKDF when deriving initial secrets and keys is SHA-256. + */ + const EVP_MD *digest = EVP_sha256(); + + uint8_t is[SHA256_DIGEST_LENGTH] = {0}; + quic_str_t initial_secret; + initial_secret.data = is; + initial_secret.len = SHA256_DIGEST_LENGTH; + + // Use dcid and initial_salt get initial_secret + if (hkdf_extract(&initial_secret, digest, dcid, initial_salt) != 0) + { + return -1; + } + quic_str_to_hex("initial_secret:",initial_secret.data, initial_secret.len); + struct + { + quic_str_t label; + quic_str_t *key; + quic_str_t *prk; + } seq[] = { + /* labels per RFC 9001, 5.1. Packet Protection Keys */ + {quic_string("tls13 server in"), &server_secret->secret, &initial_secret}, + {quic_string("tls13 quic key"), &server_secret->key, &server_secret->secret}, + {quic_string("tls13 quic iv"), &server_secret->iv, &server_secret->secret}, + {quic_string("tls13 quic hp"), &server_secret->hp, &server_secret->secret}}; + + for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) + { + if (quic_hkdf_expand(digest, seq[i].key, &seq[i].label, seq[i].prk) != 0) + { + return -1; + } + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// 对数据包进行加密,主要函数: +/////////////////////////////////////////////////////////////////////////////// + +vector get_length_variable(const vector &packet, int offset) +{ + vector result; + + int t = pow(2, packet[offset] >> 6); + result.push_back(t); + result.push_back(0); + vector subVector(packet.begin() + offset, packet.begin() + t + offset); + + for (unsigned char byte : subVector) + { + if (t != 1 && result[1] == 0) + { + byte &= 0x3f; // 对最高位两位进行设置为0 + } + result[1] = (result[1] << 8) | byte; + } + return result; +} +void LOG(const string &tips, const vector &bytes) +{ + cout << tips; + for (const unsigned char &c : bytes) + { + printf("%02X ", c); + } + cout << endl; +} + +// 生成掩码 +vector generate_mask(const vector &hp_key, const vector &sample) +{ + AES_KEY aes_key; + AES_set_encrypt_key(hp_key.data(), 128, &aes_key); + + vector encrypted(AES_BLOCK_SIZE); + memset(encrypted.data(), 0, AES_BLOCK_SIZE); + AES_ecb_encrypt(sample.data(), encrypted.data(), &aes_key, AES_ENCRYPT); + + vector mask(encrypted.begin(), encrypted.begin() + 5); + return mask; +} +// 计算数据包号的偏移 +int get_offset(const vector &plain_header) +{ + if ((plain_header[0] & 0x80) == 0x80) + { + // 长包头 + // int len_flag = 1; //1个byte c3 11000011 前5个字段 + // int len_version = 4; + // int len_dcid_len = 1; + int len_dcid = static_cast(plain_header[5]); // 正常应该是5 + // int len_scid_len = 1; + int len_scid = static_cast(plain_header[len_dcid + 6]); + + // 调用 get_length_variable 函数获取 token 变量的长度和值 + vector token_v = get_length_variable(plain_header, 7 + len_dcid + len_scid); + int len_token_len = token_v[0]; // 变长变量,00:1,01:2,10:4,11:8 + int len_token = token_v[1]; // 目前可见的都是0 + + int payload_offset = 7 + len_dcid + len_scid + len_token_len + len_token; + int len_payload_len = get_length_variable(plain_header, payload_offset)[0]; // 变长变量 + int pn_offset = 7 + len_dcid + len_scid + len_token_len + len_token + len_payload_len; + + // 打印各个变量的值 + cout << "len_dcid, len_scid, len_token_len, len_token, len_payload_len, len_token_len: " + << len_dcid << ", " << len_scid << ", " << len_token_len << ", " << len_token << ", " << len_payload_len << ", " << len_token_len << endl; + + return pn_offset; + } + else + { + // 短包头 + int pn_offset = 1 + get_length_variable(plain_header, 1)[0]; + return pn_offset; + } +} +vector apply_header_protection(const vector &mask, const vector &packet, int pn_offset, int pn_length) +{ + vector protected_packet(packet); + if ((protected_packet[0] & 0x80) == 0x80) + { + printf("长包头,掩饰4个比特位"); + // 长包头:掩饰4个比特位 + protected_packet[0] ^= (mask[0] & 0x0F); // 对保留比特位、数据包号长度进行保护 + } + else + { + printf("短包头:掩饰5个比特位"); + // 短包头:掩饰5个比特位 + protected_packet[0] ^= (mask[0] & 0x1F); + } + for (int i = 0; i < pn_length; i++) + { + protected_packet[pn_offset + i] ^= mask[1 + i]; // 对包号进行保护 + printf("%d\n\n",protected_packet[pn_offset + i]); + } + return protected_packet; +} + +// 测试用, 十六进制字符串转字节流 +vector hexStringToBytes(const string &hexString) +{ + vector bytes; + + for (size_t i = 0; i < hexString.length(); i += 2) + { + string byteString = hexString.substr(i, 2); + unsigned char byte = static_cast(stoi(byteString, nullptr, 16)); + bytes.push_back(byte); + } + + return bytes; +} + +vector encrypt_aead(const vector &key, const vector &nonce, const vector &plaintext, const vector &associated_data) +{ + int len; + vector ciphertext(plaintext.size() + EVP_MAX_BLOCK_LENGTH); + + // 初始化 + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + // 选择加密套件 + EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); + // 设置iv长度(这里输入的是nonce的,一样) + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, nonce.size(), NULL); + // 设置key,nonce + EVP_EncryptInit_ex(ctx, NULL, NULL, key.data(), nonce.data()); + // 设置关联数据 + EVP_EncryptUpdate(ctx, NULL, &len, associated_data.data(), associated_data.size()); + // 加密数据 + EVP_EncryptUpdate(ctx, ciphertext.data(), &len, plaintext.data(), plaintext.size()); + // 完成加密 + EVP_EncryptFinal_ex(ctx, ciphertext.data(), &len); + // 获取认证标签 + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, ciphertext.data() + plaintext.size()); + EVP_CIPHER_CTX_free(ctx); + + ciphertext.resize(plaintext.size() + len + 16); + return ciphertext; +} +void secretInit(quic_secret_t &server_secret){ + server_secret.secret.len = SHA256_DIGEST_LENGTH; + server_secret.secret.data = (u_char *)calloc(SHA256_DIGEST_LENGTH + 1, sizeof(u_char)); + + server_secret.key.len = QUIC_AES_128_KEY_LEN; + server_secret.key.data = (u_char *)calloc(QUIC_AES_128_KEY_LEN + 1, sizeof(u_char)); + + server_secret.hp.len = QUIC_AES_128_KEY_LEN; + server_secret.hp.data = (u_char *)calloc(QUIC_AES_128_KEY_LEN + 1, sizeof(u_char)); + + server_secret.iv.len = QUIC_IV_LEN; + server_secret.iv.data = (u_char *)calloc(QUIC_IV_LEN + 1, sizeof(u_char)); +} + +vector getProtectedPacket(vector plain_header,vector plain_payload,quic_secret_t server_secret){ + + // 从包头中获取包号的偏移量,获取包号变量长度和数值 + int pn_offset = get_offset(plain_header); + vector packet_number_vector = get_length_variable(plain_header, pn_offset); + LOG("plainHeader:",plain_header); + LOG("plainPayload:",plain_payload); + printf("包号偏移量%d\n",pn_offset); + + // 获得key,iv,hp,nonce, + vector key(server_secret.key.len); + memcpy(key.data(), server_secret.key.data, server_secret.key.len); + vector iv(server_secret.iv.len); + memcpy(iv.data(), server_secret.iv.data, server_secret.iv.len); + vector hp(server_secret.hp.len); + memcpy(hp.data(), server_secret.hp.data, server_secret.hp.len); + vector nonce(server_secret.iv.len); + memcpy(nonce.data(), server_secret.iv.data, server_secret.iv.len); //nonce最初设置和iv一样 + + // 生成nonce。 iv,packet_number->nonce + uint8_t packet_number = 0x01; // 需要同步修改builtHeader(), 实际8..32,这里默认8位,包号为1, + nonce[11] = iv[11] ^ packet_number; //修改后的iv,就是nonce,nonce = 包号填充后与iv异或 + LOG("nonce: ",nonce); + // 加密payload + vector encrptyed_payload = encrypt_aead(key, nonce, plain_payload, plain_header); + LOG("Encrptyed_payload: ",encrptyed_payload); + + // 获取sample + vector packet; + packet.reserve(plain_header.size() + encrptyed_payload.size()); + packet.insert(packet.end(),plain_header.begin(),plain_header.end()); + packet.insert(packet.end(),encrptyed_payload.begin(),encrptyed_payload.end()); + vector sample(packet.begin()+pn_offset+4, packet.begin()+pn_offset+20); + LOG("sample: ",sample); + + // 测试获取mask,用于头部保护 + vector mask = generate_mask(hp, sample); + LOG("Mask: ",mask); + + // 进行头部保护 + int pn_length = packet_number_vector[0]+1; + printf("pn_length:%d\r\n",pn_length); + vector protected_packet = apply_header_protection(mask, packet, pn_offset, pn_length); + LOG("Protected Packet: ",protected_packet); + return protected_packet; +} + +// 加密数据包+头部保护 +int test() +{ + // 测试从包头中获取包号的偏移量 + vector plain_header = hexStringToBytes("c1000000010008f067a5502a4262b50040750001"); + int pn_offset = get_offset(plain_header); + printf("包号偏移量%d",pn_offset); + + // 测试获取包号变量长度和数值 + vector packet_number_vector = get_length_variable(plain_header, pn_offset); + cout << "Length: " << packet_number_vector[0] << endl; + cout << "Value: " << packet_number_vector[1] << endl; + + // 获得key,iv,hp,nonce, + vector key = {0xcf,0x3a,0x53,0x31,0x65,0x3c,0x36,0x4c,0x88,0xf0,0xf3,0x79,0xb6,0x06,0x7e,0x37}; + vector iv = {0x0a,0xc1,0x49,0x3c,0xa1,0x90,0x58,0x53,0xb0,0xbb,0xa0,0x3e}; + vector hp = {0xc2, 0x06, 0xb8, 0xd9, 0xb9, 0xf0, 0xf3, 0x76, 0x44, 0x43, 0x0b, 0x49, 0x0e, 0xea, 0xa3, 0x14 }; + vector plaintext = hexStringToBytes("02000000000600405a020000560303eefce7f7b37ba1d1632e96677825ddf73988cfc79825df566dc5430b9a045a1200130100002e00330024001d00209d3c940d89690b84d08a60993c144eca684d1081287c834d5311bcf32bb9da1a002b00020304"); + + uint8_t packet_number = 0x01; //实际8..32,这里默认8位,包号为0 + iv[11] = iv[11] ^ packet_number; //修改后的iv,就是nonce,nonce = 包号填充后与iv异或 + + // 加密payload + vector encrptyed_payload = encrypt_aead(key, iv, plaintext, plain_header); + LOG("Encrptyed_payload: ",encrptyed_payload); + + // 获取sample + vector packet; + packet.reserve(plain_header.size() + encrptyed_payload.size()); + packet.insert(packet.end(),plain_header.begin(),plain_header.end()); + packet.insert(packet.end(),encrptyed_payload.begin(),encrptyed_payload.end()); + vector sample(packet.begin()+pn_offset+4, packet.begin()+pn_offset+20); + + // 测试获取mask,用于头部保护 + vector mask = generate_mask(hp, sample); + LOG("Mask: ",mask); + + // 进行头部保护 + int pn_length = packet_number_vector[0]+1; + vector protected_packet = apply_header_protection(mask, packet, pn_offset, pn_length); + LOG("Protected Packet: ",protected_packet); + + return 0; +} +int main() +{ + // test(); 测试单个函数用 + + //////////////////////////// + ////////解析客户端,已知信息 + //////////////////////////// + + // 设置client_dcid_vector,vector类型 + vector client_dcid_vector = hexStringToBytes("8394c8f03e515708"); //需要获取, + + quic_str_t client_dcid;// client_dcid,结构体,获取密钥用 + client_dcid.data = client_dcid_vector.data(); + client_dcid.len = client_dcid_vector.size(); + + // 设置client_scid_vector,vector类型 + vector client_scid_vector = hexStringToBytes("5555555555555555"); //需要获取, + + quic_str_t client_scid;// 服务端的dcid设置为这个值 + client_scid.data = client_scid_vector.data(); + client_scid.len = client_scid_vector.size(); + + + + //////////////////////////// + ////////服务端处理 + //////////////////////////// + + // // 服务端设置dcid,scid, vector + vector dcid_vector(client_scid.len); //需要获取client_scid,二者一致, = client_scid.data,shi + memcpy(dcid_vector.data(), client_scid.data, client_scid.len); + vector scid_vector = hexStringToBytes("f067a5502a4262b5"); //服务器手动设置 + + // //设置版本号 + uint32_t version = 2345; + + // 初始化密钥,client_dcid是结构体, 获得server_secret.key.data ,iv.data, hp.data + quic_secret_t server_secret; + secretInit(server_secret); + quic_keys_set_initial_secret(&server_secret,&client_dcid,version); + + // 打印各个密钥,测试用 + quic_str_to_hex("server_secret secret: ",server_secret.secret.data,server_secret.secret.len); + quic_str_to_hex("server_secret key: ",server_secret.key.data,server_secret.key.len); + quic_str_to_hex("server_secret iv: ",server_secret.iv.data,server_secret.iv.len); + quic_str_to_hex("server_secret hp: ",server_secret.hp.data,server_secret.hp.len); + + // 生成inital的 header,plain_payload,使用的是client_dst_connection_id,server_src_connection_id(scid) + vector> inital_quic = getIntialPlainQuic(dcid_vector, scid_vector); + printByteStream(inital_quic[0]); + printByteStream(inital_quic[1]); + vector header1 = inital_quic[0]; + vector plain_payload1 = inital_quic[1]; + + vector protected_packet = getProtectedPacket(header1,plain_payload1,server_secret); + + // // 生成handshake的 header,plain + // vector> handshake_quic = getHandshakePlainQuic(dcid_vector, scid_vector); + // printByteStream(handshake_quic[0]); + // printByteStream(handshake_quic[1]); + // vector header2 = handshake_quic[0]; + // vector plain_payload2 = handshake_quic[1]; + + + + return 0; +} +