поэтому я пишу свою собственную реализацию tls 1.2 для изучения и потому, что сервер, к которому я подключаюсь, использует измененную версию протокола, которая все равно запрашивает неслучайный client_random (TL; DR: у меняошибка bad_record_mac в готовом сообщении с моей реализацией, и я не могу найти, где я допустил ошибку)
Мне нужно указать единственное, что меня беспокоит, это TLS_RSA_WITH_AES_128_CBC_SHA
, поэтому сначала я создаюМой клиент случайный, и рукопожатие начинается с отправки сервером server_random и открытого ключа RSA в сертификате
. Я генерирую случайный pre_master_secret и шифрую его открытым ключом RSA (выполняется собственным модулем языка, поэтомуне мешайте мне в этом) и отправьте его обратно в сообщении client_key_exchange
Затем я сгенерирую master_secret из: PRF (pre_master_secret, "master secret", client_random + server_random), где PRF:
class TlsMasterSecret {
constructor(pre_master_secret, client_random, server_random) {
this.master_secret = TlsMasterSecret.PRF(pre_master_secret, Buffer.from("master secret", "ascii"), Buffer.concat([client_random, server_random]), 48);
this.master_secret = this.master_secret.slice(0, 48);
this.key_block = TlsMasterSecret.PRF(this.master_secret, Buffer.from("key expansion", "ascii"),Buffer.concat([server_random, client_random]), 104);
// 20 20 16 16
this.client_write_MAC_key = this.key_block.slice(0, 20);
this.server_write_MAC_key = this.key_block.slice(20, 40);
this.client_write_key = this.key_block.slice(40, 56);
this.server_write_key = this.key_block.slice(56, 72);
}
static PRF(secret, label, seed, neededLength) {
return TlsMasterSecret.P_hash(secret, Buffer.concat([label, seed]), neededLength)
}
static P_hash(secret, seed, neededLength) {
const A = [seed];
let resultHash = Buffer.from("", "hex");
// HMAC_SHA256 generates 32 bytes per update
const iterations = Math.ceil(neededLength / 32);
// generate A
for(let i = 1; i < iterations + 1; i++) {
A[i] = TlsMasterSecret.HMAC_hash(secret, A[i-1]);
}
// calculates the hash
for(let i = 1; i < iterations + 1; i++) {
resultHash = Buffer.concat([resultHash, TlsMasterSecret.HMAC_hash(secret, A[i])]);
}
return resultHash;
}
static HMAC_hash(secret, seed) {
const hmac = crypto.createHmac("sha256", secret);
hmac.update(seed);
return hmac.digest();
}
}
затем я создаю сообщение Finished от 0x1400000cd на 12 байтов verify_data
verify_data генерируется так:
// I strip the record layer headers off the messages
client_hello = 0x0100002f03032668f90d7d3b3420f7712a3004247d233d90cc63fb4b23f77912b31c8c89893b000008002f0035003c003d0100
server_hello = 0x0200002603031296263fba0a7955a83b2bf9c3716c8ee1c52e9065b89ee5649b31391d7ce84700002f00
certificate = 0b00034e00034b00034830820344308202ada00302.......
server_hello_done = 0e000000
client_key_exchange = 100000820080673f1772e35c7565a1e0c2fae5ee1b5bf92211ba9e4de14620f43856d954cf737aa04c48f8b2ffa182f652fedd68523056acda3c7cd101c5a2c3a625655df67ad9fb7ca082cf68476f174ea7b83eab980b7b15657036ad0e26883c9bfe368847a02b052817cb80dabafc6af1dac8064ea0dc676e0f8ea74f84a122135f31b612
handshake_messages = client_hello + server_hello + certificate + server_hello_done + client_key_exchange
verify_data = PRF(master_secret, "client finished", sha256(handshake_messages))[0..12]
, тогда я создаю MAC, который будет идти по этому сообщению:
// hmac_sha1(secret, seed)
// seq_num is a uint64 @ 0 for the first message, 0x00000000
// type = 0x16
// version = 0x0303
// length = 0x0010
// content = 0x1400000c + verify_data
MAC = hmac_sha1(client_write_MAC_key, seq_num + type + version + length + content)
plaintext = content + MAC
IV = randomBytes(16)
// aes_128_cbc(key, IV, message)
ciphertext = aes_128_cbc(client_write_key, IV, plaintext)
final = 0x16 + 0x0303 + 0x0040 + IV + ciphertext
, если выпрочитайте все это и все еще готовы помочь вам большое спасибо, я думаю, что я следовал спецификации, но я получаю ошибку bad_record_mac в wireshark, так что где-то что-то не так, я просто не могу найти это: (