007-网络安全协议
难度:🔴 | 预计时间:120分钟 | 前置:006-数字证书与PKI体系
学习目标
- 理解网络安全协议的设计原理和安全目标
- 掌握SSL/TLS协议的握手过程和安全机制
- 了解IPSec、SSH、HTTPS等重要安全协议
- 熟悉无线网络安全协议(WPA/WPA2/WPA3)
- 能够分析和配置各种网络安全协议
内容正文
网络安全协议概述
网络安全协议是在网络通信中提供安全服务的协议,通过密码学技术实现机密性、完整性、认证和不可否认性。
网络安全协议分层
安全协议设计原则
| 原则 | 描述 | 实现方式 |
|---|---|---|
| 最小权限 | 只授予必要的访问权限 | 细粒度访问控制 |
| 深度防御 | 多层安全保护 | 协议栈各层都有安全措施 |
| 故障安全 | 系统故障时保持安全 | 默认拒绝策略 |
| 开放设计 | 安全不依赖于保密 | 公开协议规范 |
| 完全中介 | 所有访问都经过安全检查 | 强制访问控制 |
SSL/TLS协议
SSL/TLS(Secure Sockets Layer/Transport Layer Security)是最重要的传输层安全协议。
TLS协议架构
TLS协议类设计
TLS握手过程详解
# 文件路径: crypto/tls_handshake.py
import ssl
import socket
import struct
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import os
class TLSHandshakeAnalyzer:
"""TLS握手分析器"""
def __init__(self):
self.client_random = None
self.server_random = None
self.premaster_secret = None
self.master_secret = None
self.session_keys = None
def analyze_client_hello(self, client_hello_data):
"""分析ClientHello消息"""
# 解析TLS版本
tls_version = struct.unpack('>H', client_hello_data[0:2])[0]
# 解析客户端随机数
self.client_random = client_hello_data[2:34]
# 解析会话ID长度
session_id_length = client_hello_data[34]
session_id = client_hello_data[35:35+session_id_length]
# 解析密码套件
offset = 35 + session_id_length
cipher_suites_length = struct.unpack('>H', client_hello_data[offset:offset+2])[0]
cipher_suites_data = client_hello_data[offset+2:offset+2+cipher_suites_length]
cipher_suites = []
for i in range(0, cipher_suites_length, 2):
suite = struct.unpack('>H', cipher_suites_data[i:i+2])[0]
cipher_suites.append(suite)
return {
'tls_version': f"0x{tls_version:04x}",
'client_random': self.client_random.hex(),
'session_id': session_id.hex() if session_id else None,
'cipher_suites': [f"0x{suite:04x}" for suite in cipher_suites]
}
def generate_master_secret(self, premaster_secret, client_random, server_random):
"""生成主密钥"""
# TLS 1.2 PRF函数实现
def prf(secret, label, seed, length):
"""伪随机函数"""
import hmac
def p_hash(secret, seed, length):
"""P_hash函数"""
result = b''
a = seed
while len(result) < length:
a = hmac.new(secret, a, hashes.SHA256()).digest()
result += hmac.new(secret, a + seed, hashes.SHA256()).digest()
return result[:length]
return p_hash(secret, label + seed, length)
# 计算主密钥
label = b"master secret"
seed = client_random + server_random
master_secret = prf(premaster_secret, label, seed, 48)
self.master_secret = master_secret
return master_secret
def generate_session_keys(self, master_secret, client_random, server_random):
"""生成会话密钥"""
def prf(secret, label, seed, length):
import hmac
def p_hash(secret, seed, length):
result = b''
a = seed
while len(result) < length:
a = hmac.new(secret, a, hashes.SHA256()).digest()
result += hmac.new(secret, a + seed, hashes.SHA256()).digest()
return result[:length]
return p_hash(secret, label + seed, length)
# 生成密钥材料
label = b"key expansion"
seed = server_random + client_random
key_material = prf(master_secret, label, seed, 104) # 假设AES-128-CBC-SHA
# 分割密钥材料
client_mac_key = key_material[0:20] # SHA-1 MAC密钥
server_mac_key = key_material[20:40]
client_enc_key = key_material[40:56] # AES-128加密密钥
server_enc_key = key_material[56:72]
client_iv = key_material[72:88] # AES-128 IV
server_iv = key_material[88:104]
self.session_keys = {
'client_mac_key': client_mac_key,
'server_mac_key': server_mac_key,
'client_enc_key': client_enc_key,
'server_enc_key': server_enc_key,
'client_iv': client_iv,
'server_iv': server_iv
}
return self.session_keys
def demonstrate_tls_handshake():
"""演示TLS握手过程"""
print("=== TLS握手过程演示 ===\n")
# 1. ClientHello
print("1. ClientHello")
print(" - TLS版本: 1.2")
print(" - 客户端随机数: 32字节")
print(" - 支持的密码套件:")
print(" * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
print(" * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384")
print(" * TLS_RSA_WITH_AES_128_CBC_SHA")
# 2. ServerHello
print("\n2. ServerHello")
print(" - 选择TLS版本: 1.2")
print(" - 服务器随机数: 32字节")
print(" - 选择密码套件: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
# 3. Certificate
print("\n3. Certificate")
print(" - 服务器证书链")
print(" - 包含服务器公钥")
# 4. ServerKeyExchange (ECDHE)
print("\n4. ServerKeyExchange")
print(" - ECDHE参数")
print(" - 服务器签名")
# 5. ServerHelloDone
print("\n5. ServerHelloDone")
# 6. ClientKeyExchange
print("\n6. ClientKeyExchange")
print(" - 客户端ECDHE参数")
print(" - 计算预主密钥")
# 7. ChangeCipherSpec
print("\n7. ChangeCipherSpec (客户端)")
print(" - 激活新的密码参数")
# 8. Finished
print("\n8. Finished (客户端)")
print(" - 握手消息的MAC验证")
# 9. ChangeCipherSpec
print("\n9. ChangeCipherSpec (服务器)")
# 10. Finished
print("\n10. Finished (服务器)")
print(" - 握手完成")
print("\n=== 握手完成,开始应用数据传输 ===")
def analyze_cipher_suite(cipher_suite_hex):
"""分析密码套件"""
cipher_suites = {
0xC02F: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
0xC030: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
0x002F: "TLS_RSA_WITH_AES_128_CBC_SHA",
0x0035: "TLS_RSA_WITH_AES_256_CBC_SHA",
0xC013: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
0xC014: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"
}
suite_name = cipher_suites.get(cipher_suite_hex, f"Unknown (0x{cipher_suite_hex:04x})")
# 解析密码套件组件
if "ECDHE" in suite_name:
key_exchange = "ECDHE (椭圆曲线Diffie-Hellman临时)"
elif "RSA" in suite_name and "ECDHE" not in suite_name:
key_exchange = "RSA"
else:
key_exchange = "Unknown"
if "AES_128_GCM" in suite_name:
encryption = "AES-128-GCM"
elif "AES_256_GCM" in suite_name:
encryption = "AES-256-GCM"
elif "AES_128_CBC" in suite_name:
encryption = "AES-128-CBC"
elif "AES_256_CBC" in suite_name:
encryption = "AES-256-CBC"
else:
encryption = "Unknown"
if "SHA256" in suite_name:
mac = "SHA-256"
elif "SHA384" in suite_name:
mac = "SHA-384"
elif "SHA" in suite_name:
mac = "SHA-1"
else:
mac = "AEAD" if "GCM" in suite_name else "Unknown"
return {
'name': suite_name,
'key_exchange': key_exchange,
'encryption': encryption,
'mac': mac
}
# 示例使用
if __name__ == "__main__":
# 演示TLS握手
demonstrate_tls_handshake()
print("\n" + "="*50)
# 分析密码套件
cipher_suite = 0xC02F
analysis = analyze_cipher_suite(cipher_suite)
print(f"\n密码套件分析: 0x{cipher_suite:04x}")
print(f"名称: {analysis['name']}")
print(f"密钥交换: {analysis['key_exchange']}")
print(f"加密算法: {analysis['encryption']}")
print(f"MAC算法: {analysis['mac']}")
TLS 1.3的改进
TLS安全配置最佳实践
# 文件路径: crypto/tls_security_config.py
import ssl
def create_secure_ssl_context(is_server=False):
"""创建安全的SSL上下文"""
if is_server:
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
else:
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# 设置最低TLS版本
context.minimum_version = ssl.TLSVersion.TLSv1_2
# 禁用不安全的协议
context.options |= ssl.OP_NO_SSLv2
context.options |= ssl.OP_NO_SSLv3
context.options |= ssl.OP_NO_TLSv1
context.options |= ssl.OP_NO_TLSv1_1
# 禁用压缩(防止CRIME攻击)
context.options |= ssl.OP_NO_COMPRESSION
# 设置安全的密码套件
secure_ciphers = [
'ECDHE+AESGCM',
'ECDHE+CHACHA20',
'DHE+AESGCM',
'DHE+CHACHA20',
'!aNULL',
'!eNULL',
'!EXPORT',
'!DES',
'!RC4',
'!MD5',
'!PSK',
'!SRP',
'!CAMELLIA'
]
context.set_ciphers(':'.join(secure_ciphers))
if is_server:
# 服务器配置
context.options |= ssl.OP_CIPHER_SERVER_PREFERENCE
# 启用OCSP装订
context.options |= ssl.OP_TLSEXT_PADDING
else:
# 客户端配置
context.check_hostname = True
context.verify_mode = ssl.CERT_REQUIRED
return context
def analyze_ssl_connection(hostname, port=443):
"""分析SSL连接安全性"""
context = ssl.create_default_context()
with socket.create_connection((hostname, port)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
# 获取连接信息
cipher = ssock.cipher()
version = ssock.version()
cert = ssock.getpeercert()
# 分析安全性
security_analysis = {
'protocol_version': version,
'cipher_suite': cipher[0] if cipher else None,
'key_exchange': cipher[1] if cipher else None,
'encryption_strength': cipher[2] if cipher else None,
'certificate_info': {
'subject': cert.get('subject'),
'issuer': cert.get('issuer'),
'version': cert.get('version'),
'serial_number': cert.get('serialNumber'),
'not_before': cert.get('notBefore'),
'not_after': cert.get('notAfter')
}
}
# 安全评估
security_score = 0
recommendations = []
# 协议版本评估
if version == 'TLSv1.3':
security_score += 30
elif version == 'TLSv1.2':
security_score += 25
else:
recommendations.append(f"升级到TLS 1.2或更高版本(当前:{version})")
# 密码套件评估
if cipher and 'GCM' in cipher[0]:
security_score += 25
elif cipher and 'CBC' in cipher[0]:
security_score += 15
recommendations.append("建议使用AEAD密码套件(如GCM)")
# 密钥长度评估
if cipher and cipher[2] >= 256:
security_score += 25
elif cipher and cipher[2] >= 128:
security_score += 20
else:
recommendations.append("使用更长的加密密钥")
# 证书评估
if cert:
security_score += 20
security_analysis['security_score'] = security_score
security_analysis['recommendations'] = recommendations
return security_analysis
IPSec协议
IPSec(Internet Protocol Security)是网络层安全协议,提供端到端的安全通信。
IPSec架构
IPSec工作模式
# 文件路径: crypto/ipsec_modes.py
import struct
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import hashes, hmac
import os
class IPSecProcessor:
"""IPSec处理器"""
def __init__(self, encryption_key, auth_key):
self.encryption_key = encryption_key
self.auth_key = auth_key
def esp_encrypt_transport_mode(self, ip_packet, spi, seq_num):
"""ESP传输模式加密"""
# 解析IP包
ip_header = ip_packet[:20] # 假设标准IP头
payload = ip_packet[20:]
# 创建ESP头
esp_header = struct.pack('>II', spi, seq_num)
# 添加填充
block_size = 16 # AES块大小
pad_length = block_size - (len(payload) % block_size)
if pad_length == block_size:
pad_length = 0
padding = bytes(range(1, pad_length + 1))
padded_payload = payload + padding + bytes([pad_length])
# 加密载荷
iv = os.urandom(16)
cipher = Cipher(algorithms.AES(self.encryption_key), modes.CBC(iv))
encryptor = cipher.encryptor()
encrypted_payload = encryptor.update(padded_payload) + encryptor.finalize()
# 构造ESP包
esp_packet = esp_header + iv + encrypted_payload
# 计算认证数据
h = hmac.HMAC(self.auth_key, hashes.SHA256())
h.update(esp_packet)
auth_data = h.finalize()[:12] # 截取前12字节
# 构造最终包
final_packet = ip_header + esp_packet + auth_data
return final_packet
def esp_decrypt_transport_mode(self, esp_packet):
"""ESP传输模式解密"""
# 解析包结构
ip_header = esp_packet[:20]
esp_data = esp_packet[20:-12]
auth_data = esp_packet[-12:]
# 验证认证数据
h = hmac.HMAC(self.auth_key, hashes.SHA256())
h.update(ip_header + esp_data)
expected_auth = h.finalize()[:12]
if auth_data != expected_auth:
raise ValueError("ESP认证失败")
# 解析ESP头
spi, seq_num = struct.unpack('>II', esp_data[:8])
iv = esp_data[8:24]
encrypted_payload = esp_data[24:]
# 解密载荷
cipher = Cipher(algorithms.AES(self.encryption_key), modes.CBC(iv))
decryptor = cipher.decryptor()
decrypted_payload = decryptor.update(encrypted_payload) + decryptor.finalize()
# 移除填充
pad_length = decrypted_payload[-1]
original_payload = decrypted_payload[:-(pad_length + 1)]
# 重构原始IP包
original_packet = ip_header + original_payload
return original_packet, spi, seq_num
def esp_encrypt_tunnel_mode(self, ip_packet, spi, seq_num, tunnel_src, tunnel_dst):
"""ESP隧道模式加密"""
# 创建新的IP头(隧道头)
tunnel_ip_header = self.create_ip_header(tunnel_src, tunnel_dst, len(ip_packet))
# 创建ESP头
esp_header = struct.pack('>II', spi, seq_num)
# 添加填充
block_size = 16
pad_length = block_size - (len(ip_packet) % block_size)
if pad_length == block_size:
pad_length = 0
padding = bytes(range(1, pad_length + 1))
padded_payload = ip_packet + padding + bytes([pad_length])
# 加密整个原始IP包
iv = os.urandom(16)
cipher = Cipher(algorithms.AES(self.encryption_key), modes.CBC(iv))
encryptor = cipher.encryptor()
encrypted_payload = encryptor.update(padded_payload) + encryptor.finalize()
# 构造ESP包
esp_packet = esp_header + iv + encrypted_payload
# 计算认证数据
h = hmac.HMAC(self.auth_key, hashes.SHA256())
h.update(esp_packet)
auth_data = h.finalize()[:12]
# 构造最终隧道包
tunnel_packet = tunnel_ip_header + esp_packet + auth_data
return tunnel_packet
def create_ip_header(self, src_ip, dst_ip, payload_length):
"""创建IP头"""
# 简化的IP头创建
version_ihl = 0x45 # IPv4, 20字节头长度
tos = 0
total_length = 20 + payload_length
identification = 0
flags_fragment = 0
ttl = 64
protocol = 50 # ESP协议号
checksum = 0 # 简化,实际需要计算
# 转换IP地址
src_bytes = bytes(map(int, src_ip.split('.')))
dst_bytes = bytes(map(int, dst_ip.split('.')))
ip_header = struct.pack('>BBHHHBBH4s4s',
version_ihl, tos, total_length,
identification, flags_fragment,
ttl, protocol, checksum,
src_bytes, dst_bytes)
return ip_header
def demonstrate_ipsec_modes():
"""演示IPSec工作模式"""
# 生成密钥
encryption_key = os.urandom(32) # AES-256
auth_key = os.urandom(32) # HMAC-SHA256
processor = IPSecProcessor(encryption_key, auth_key)
# 模拟原始IP包
original_packet = b'\x45\x00\x00\x54' + b'\x00' * 16 + b'Hello, IPSec!'
print("=== IPSec模式演示 ===")
print(f"原始包长度: {len(original_packet)} 字节")
# 传输模式
print("\n1. ESP传输模式:")
encrypted_transport = processor.esp_encrypt_transport_mode(
original_packet, spi=0x12345678, seq_num=1
)
print(f" 加密后长度: {len(encrypted_transport)} 字节")
decrypted_transport, spi, seq = processor.esp_decrypt_transport_mode(encrypted_transport)
print(f" 解密后长度: {len(decrypted_transport)} 字节")
print(f" SPI: 0x{spi:08x}, 序列号: {seq}")
# 隧道模式
print("\n2. ESP隧道模式:")
encrypted_tunnel = processor.esp_encrypt_tunnel_mode(
original_packet, spi=0x87654321, seq_num=2,
tunnel_src="192.168.1.1", tunnel_dst="10.0.0.1"
)
print(f" 隧道包长度: {len(encrypted_tunnel)} 字节")
SSH协议
SSH(Secure Shell)是应用层安全协议,主要用于远程登录和文件传输。
SSH协议架构
SSH密钥交换过程
# 文件路径: crypto/ssh_protocol.py
import hashlib
import struct
from cryptography.hazmat.primitives.asymmetric import rsa, dsa
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
import base64
class SSHKeyExchange:
"""SSH密钥交换实现"""
def __init__(self):
self.client_version = "SSH-2.0-OpenSSH_8.0"
self.server_version = "SSH-2.0-OpenSSH_8.0"
self.client_kexinit = None
self.server_kexinit = None
self.shared_secret = None
self.exchange_hash = None
def create_kexinit_packet(self, is_server=False):
"""创建密钥交换初始化包"""
# 支持的算法列表
kex_algorithms = [
"diffie-hellman-group14-sha256",
"ecdh-sha2-nistp256",
"ecdh-sha2-nistp384"
]
server_host_key_algorithms = [
"rsa-sha2-512",
"rsa-sha2-256",
"ssh-rsa",
"ecdsa-sha2-nistp256"
]
encryption_algorithms = [
"aes128-ctr",
"aes192-ctr",
"aes256-ctr",
"aes128-gcm@openssh.com",
"aes256-gcm@openssh.com"
]
mac_algorithms = [
"hmac-sha2-256",
"hmac-sha2-512",
"hmac-sha1"
]
compression_algorithms = [
"none",
"zlib@openssh.com"
]
# 构造KEXINIT包
kexinit_data = {
'kex_algorithms': kex_algorithms,
'server_host_key_algorithms': server_host_key_algorithms,
'encryption_algorithms_client_to_server': encryption_algorithms,
'encryption_algorithms_server_to_client': encryption_algorithms,
'mac_algorithms_client_to_server': mac_algorithms,
'mac_algorithms_server_to_client': mac_algorithms,
'compression_algorithms_client_to_server': compression_algorithms,
'compression_algorithms_server_to_client': compression_algorithms
}
if is_server:
self.server_kexinit = kexinit_data
else:
self.client_kexinit = kexinit_data
return kexinit_data
def perform_dh_key_exchange(self, p, g, server_private_key=None):
"""执行Diffie-Hellman密钥交换"""
import random
# 生成客户端私钥
client_private = random.randint(2, p-2)
client_public = pow(g, client_private, p)
if server_private_key is None:
# 生成服务器私钥
server_private = random.randint(2, p-2)
else:
server_private = server_private_key
server_public = pow(g, server_private, p)
# 计算共享密钥
shared_secret_client = pow(server_public, client_private, p)
shared_secret_server = pow(client_public, server_private, p)
assert shared_secret_client == shared_secret_server
self.shared_secret = shared_secret_client
return {
'client_public': client_public,
'server_public': server_public,
'shared_secret': shared_secret_client
}
def compute_exchange_hash(self, client_public, server_public, server_host_key):
"""计算交换哈希"""
# SSH交换哈希计算
hash_data = b''
# 添加版本字符串
hash_data += self._ssh_string(self.client_version.encode())
hash_data += self._ssh_string(self.server_version.encode())
# 添加KEXINIT数据(简化)
hash_data += self._ssh_string(str(self.client_kexinit).encode())
hash_data += self._ssh_string(str(self.server_kexinit).encode())
# 添加服务器主机密钥
hash_data += self._ssh_string(server_host_key)
# 添加DH公钥
hash_data += self._ssh_mpint(client_public)
hash_data += self._ssh_mpint(server_public)
# 添加共享密钥
hash_data += self._ssh_mpint(self.shared_secret)
# 计算SHA-256哈希
self.exchange_hash = hashlib.sha256(hash_data).digest()
return self.exchange_hash
def derive_keys(self, shared_secret, exchange_hash, session_id):
"""派生会话密钥"""
def derive_key(shared_secret, exchange_hash, session_id, key_id, key_length):
"""派生单个密钥"""
hash_data = self._ssh_mpint(shared_secret) + exchange_hash + key_id + session_id
key = hashlib.sha256(hash_data).digest()
# 如果需要更长的密钥,继续哈希
while len(key) < key_length:
hash_data = self._ssh_mpint(shared_secret) + exchange_hash + key
key += hashlib.sha256(hash_data).digest()
return key[:key_length]
# 派生各种密钥
keys = {
'client_to_server_iv': derive_key(shared_secret, exchange_hash, session_id, b'A', 16),
'server_to_client_iv': derive_key(shared_secret, exchange_hash, session_id, b'B', 16),
'client_to_server_encryption': derive_key(shared_secret, exchange_hash, session_id, b'C', 32),
'server_to_client_encryption': derive_key(shared_secret, exchange_hash, session_id, b'D', 32),
'client_to_server_mac': derive_key(shared_secret, exchange_hash, session_id, b'E', 32),
'server_to_client_mac': derive_key(shared_secret, exchange_hash, session_id, b'F', 32)
}
return keys
def _ssh_string(self, data):
"""SSH字符串编码"""
return struct.pack('>I', len(data)) + data
def _ssh_mpint(self, number):
"""SSH多精度整数编码"""
if number == 0:
return struct.pack('>I', 0)
# 转换为字节
byte_length = (number.bit_length() + 7) // 8
bytes_data = number.to_bytes(byte_length, 'big')
# 如果最高位是1,需要添加0x00前缀
if bytes_data[0] & 0x80:
bytes_data = b'\x00' + bytes_data
return struct.pack('>I', len(bytes_data)) + bytes_data
def demonstrate_ssh_handshake():
"""演示SSH握手过程"""
print("=== SSH握手过程演示 ===")
ssh_kex = SSHKeyExchange()
# 1. 版本交换
print("1. 版本交换")
print(f" 客户端: {ssh_kex.client_version}")
print(f" 服务器: {ssh_kex.server_version}")
# 2. 算法协商
print("\n2. 算法协商 (KEXINIT)")
client_kexinit = ssh_kex.create_kexinit_packet(is_server=False)
server_kexinit = ssh_kex.create_kexinit_packet(is_server=True)
print(" 支持的密钥交换算法:")
for alg in client_kexinit['kex_algorithms'][:3]:
print(f" - {alg}")
# 3. 密钥交换
print("\n3. Diffie-Hellman密钥交换")
# 使用RFC 3526 Group 14参数
p = int("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
"15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
g = 2
dh_result = ssh_kex.perform_dh_key_exchange(p, g)
print(f" 共享密钥已生成 (长度: {dh_result['shared_secret'].bit_length()} 位)")
# 4. 服务器认证
print("\n4. 服务器主机密钥验证")
# 生成模拟的服务器密钥
server_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
server_public_key_bytes = server_key.public_key().public_bytes(
encoding=serialization.Encoding.OpenSSH,
format=serialization.PublicFormat.OpenSSH
)
# 计算交换哈希
exchange_hash = ssh_kex.compute_exchange_hash(
dh_result['client_public'],
dh_result['server_public'],
server_public_key_bytes
)
print(f" 交换哈希: {exchange_hash.hex()[:32]}...")
# 5. 密钥派生
print("\n5. 会话密钥派生")
session_keys = ssh_kex.derive_keys(
dh_result['shared_secret'],
exchange_hash,
exchange_hash # 第一次连接时session_id = exchange_hash
)
print(" 派生的密钥:")
for key_name, key_value in session_keys.items():
print(f" {key_name}: {key_value.hex()[:16]}...")
print("\n=== SSH握手完成 ===")
# 示例使用
if __name__ == "__main__":
demonstrate_ssh_handshake()
无线网络安全协议
WPA/WPA2/WPA3演进
WPA2四次握手
# 文件路径: crypto/wpa2_handshake.py
import hashlib
import hmac
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
import os
class WPA2HandshakeProcessor:
"""WPA2四次握手处理器"""
def __init__(self, ssid, passphrase):
self.ssid = ssid
self.passphrase = passphrase
self.pmk = self.derive_pmk()
self.ptk = None
self.gtk = None
def derive_pmk(self):
"""派生预共享主密钥PMK"""
# 使用PBKDF2派生PMK
kdf = PBKDF2HMAC(
algorithm=hashes.SHA1(),
length=32, # PMK长度为256位
salt=self.ssid.encode(),
iterations=4096
)
pmk = kdf.derive(self.passphrase.encode())
return pmk
def derive_ptk(self, ap_mac, sta_mac, anonce, snonce):
"""派生成对临时密钥PTK"""
# PTK = PRF-512(PMK, "Pairwise key expansion",
# Min(AP_MAC, STA_MAC) || Max(AP_MAC, STA_MAC) ||
# Min(ANonce, SNonce) || Max(ANonce, SNonce))
# 确定MAC地址顺序
if ap_mac < sta_mac:
mac_data = ap_mac + sta_mac
else:
mac_data = sta_mac + ap_mac
# 确定Nonce顺序
if anonce < snonce:
nonce_data = anonce + snonce
else:
nonce_data = snonce + anonce
# 构造PRF输入
prf_input = b"Pairwise key expansion\x00" + mac_data + nonce_data
# 使用PRF-512生成PTK
ptk = self.prf_512(self.pmk, prf_input)
# PTK分解
self.ptk = {
'kck': ptk[0:16], # 密钥确认密钥
'kek': ptk[16:32], # 密钥加密密钥
'tk': ptk[32:48], # 临时密钥
'mic_key': ptk[48:64] # MIC密钥
}
return self.ptk
def prf_512(self, key, data):
"""伪随机函数PRF-512"""
result = b''
i = 0
while len(result) < 64: # 512位 = 64字节
h = hmac.new(key, data + bytes([i]), hashlib.sha1)
result += h.digest()
i += 1
return result[:64]
def calculate_mic(self, eapol_frame, key_type='ptk'):
"""计算MIC"""
if key_type == 'ptk' and self.ptk:
mic_key = self.ptk['kck']
else:
raise ValueError("PTK未生成或密钥类型错误")
# 将MIC字段清零
frame_copy = bytearray(eapol_frame)
# 假设MIC字段在特定位置(实际需要根据EAPOL格式解析)
mic_offset = len(frame_copy) - 16
frame_copy[mic_offset:mic_offset+16] = b'\x00' * 16
# 计算HMAC-MD5
h = hmac.new(mic_key, bytes(frame_copy), hashlib.md5)
return h.digest()
def verify_mic(self, eapol_frame, received_mic):
"""验证MIC"""
calculated_mic = self.calculate_mic(eapol_frame)
return calculated_mic == received_mic
def demonstrate_wpa2_handshake():
"""演示WPA2四次握手"""
print("=== WPA2四次握手演示 ===")
# 网络参数
ssid = "TestNetwork"
passphrase = "SecurePassword123"
ap_mac = bytes.fromhex("001122334455")
sta_mac = bytes.fromhex("aabbccddeeff")
# 创建处理器
wpa2 = WPA2HandshakeProcessor(ssid, passphrase)
print(f"网络SSID: {ssid}")
print(f"预共享密钥: {passphrase}")
print(f"PMK: {wpa2.pmk.hex()}")
# 生成随机数
anonce = os.urandom(32) # AP随机数
snonce = os.urandom(32) # STA随机数
print(f"\nAP随机数: {anonce.hex()[:32]}...")
print(f"STA随机数: {snonce.hex()[:32]}...")
# 派生PTK
ptk = wpa2.derive_ptk(ap_mac, sta_mac, anonce, snonce)
print(f"\n派生的PTK组件:")
print(f"KCK (密钥确认密钥): {ptk['kck'].hex()}")
print(f"KEK (密钥加密密钥): {ptk['kek'].hex()}")
print(f"TK (临时密钥): {ptk['tk'].hex()}")
# 模拟四次握手过程
print(f"\n=== 四次握手过程 ===")
print("1. AP -> STA: EAPOL-Key (ANonce)")
print(" - 包含AP随机数")
print(" - 启动握手过程")
print("\n2. STA -> AP: EAPOL-Key (SNonce + MIC)")
print(" - 包含STA随机数")
print(" - 包含MIC验证")
print(" - STA已计算PTK")
print("\n3. AP -> STA: EAPOL-Key (GTK + MIC)")
print(" - 安装PTK")
print(" - 传输组临时密钥GTK")
print(" - 包含MIC验证")
print("\n4. STA -> AP: EAPOL-Key (确认)")
print(" - 确认密钥安装")
print(" - 握手完成")
print(f"\n=== 握手完成,开始数据传输 ===")
# WPA3 SAE认证
class WPA3SAEProcessor:
"""WPA3 SAE (Simultaneous Authentication of Equals) 处理器"""
def __init__(self, password):
self.password = password
self.pwe = None # Password Element
self.pmk = None
def derive_pwe(self, mac1, mac2, ssid):
"""派生密码元素PWE"""
# SAE使用椭圆曲线或有限域群
# 这里简化实现概念
# 构造标识符
identifier = mac1 + mac2 + ssid.encode()
# 使用密码和标识符派生PWE
# 实际实现需要使用特定的椭圆曲线算法
hash_input = self.password.encode() + identifier
self.pwe = hashlib.sha256(hash_input).digest()
return self.pwe
def sae_commit(self, mac1, mac2, ssid):
"""SAE Commit阶段"""
# 派生PWE
pwe = self.derive_pwe(mac1, mac2, ssid)
# 生成随机标量和元素
scalar = os.urandom(32)
element = os.urandom(32) # 简化表示
return {
'scalar': scalar,
'element': element,
'pwe': pwe
}
def sae_confirm(self, commit_data, peer_commit):
"""SAE Confirm阶段"""
# 计算确认值
confirm_input = (commit_data['scalar'] +
commit_data['element'] +
peer_commit['scalar'] +
peer_commit['element'])
confirm = hmac.new(self.pwe, confirm_input, hashlib.sha256).digest()
return confirm
def demonstrate_wpa3_sae():
"""演示WPA3 SAE认证"""
print("\n=== WPA3 SAE认证演示 ===")
password = "SecureWPA3Password"
ssid = "WPA3Network"
# 设备MAC地址
ap_mac = bytes.fromhex("001122334455")
sta_mac = bytes.fromhex("aabbccddeeff")
# 创建SAE处理器
ap_sae = WPA3SAEProcessor(password)
sta_sae = WPA3SAEProcessor(password)
print(f"网络: {ssid}")
print(f"密码: {password}")
# SAE Commit阶段
print(f"\n1. SAE Commit阶段")
ap_commit = ap_sae.sae_commit(ap_mac, sta_mac, ssid)
sta_commit = sta_sae.sae_commit(sta_mac, ap_mac, ssid)
print(f" AP Commit: {ap_commit['scalar'].hex()[:16]}...")
print(f" STA Commit: {sta_commit['scalar'].hex()[:16]}...")
# SAE Confirm阶段
print(f"\n2. SAE Confirm阶段")
ap_confirm = ap_sae.sae_confirm(ap_commit, sta_commit)
sta_confirm = sta_sae.sae_confirm(sta_commit, ap_commit)
print(f" AP Confirm: {ap_confirm.hex()[:16]}...")
print(f" STA Confirm: {sta_confirm.hex()[:16]}...")
print(f"\n=== SAE认证完成 ===")
# 示例使用
if __name__ == "__main__":
demonstrate_wpa2_handshake()
demonstrate_wpa3_sae()
实践练习
练习1:TLS协议分析
任务:分析真实的TLS握手过程
- 使用Wireshark捕获TLS握手包
- 分析密码套件选择和证书验证
- 识别可能的安全问题
验收标准:能够完整分析TLS握手的每个步骤。
练习2:IPSec VPN配置
任务:配置IPSec VPN隧道
- 设置IKE参数和安全策略
- 配置ESP隧道模式
- 测试连通性和安全性
验收标准:成功建立安全的VPN连接。
练习3:无线网络安全评估
任务:评估无线网络安全配置
- 分析WPA2/WPA3配置
- 检测常见安全漏洞
- 提出安全改进建议
验收标准:提供完整的安全评估报告。
常见问题(FAQ)
Q1:TLS 1.2和TLS 1.3有什么主要区别?
A:主要区别:
- 握手轮次:TLS 1.3只需1-RTT,TLS 1.2需要2-RTT
- 加密算法:TLS 1.3移除了不安全的算法
- 前向保密:TLS 1.3强制使用前向保密
- 握手加密:TLS 1.3对握手消息进行加密
Q2:如何选择合适的IPSec模式?
A:选择标准:
- 传输模式:端到端通信,保护上层协议
- 隧道模式:网关到网关,完整IP包保护
- AH协议:只需要认证,不需要加密
- ESP协议:需要认证和加密
Q3:SSH密钥认证比密码认证安全在哪里?
A:优势包括:
- 抗暴力破解:私钥长度远超密码复杂度
- 无网络传输:私钥不在网络上传输
- 可撤销性:可以单独撤销公钥
- 审计能力:可以追踪密钥使用
Q4:WPA3相比WPA2有哪些改进?
A:主要改进:
- SAE认证:抗离线字典攻击
- 前向保密:历史数据保护
- 增强加密:192位安全级别
- 简化配置:Wi-Fi Easy Connect
总结
本章详细介绍了网络安全协议,主要包括:
- 协议分层:不同层次的安全协议及其作用
- SSL/TLS:传输层安全协议的握手和加密机制
- IPSec:网络层安全协议的架构和工作模式
- SSH协议:安全远程访问协议的认证和加密
- 无线安全:WPA/WPA2/WPA3的演进和安全机制
网络安全协议是构建安全通信的基础,理解其原理对于网络安全至关重要。
下一步
- 前往:008-网络威胁与攻击技术
- 扩展阅读:《网络安全协议》Charlie Kaufman
- 实践建议:搭建测试环境验证各种安全协议
参考与引用
- RFC 8446 - TLS 1.3协议 (2018)
- RFC 4301 - IP安全架构 (2005)
- RFC 4251 - SSH协议架构 (2006)
- IEEE 802.11i - 无线局域网安全 (2004)
更新记录
- 更新时间: 2024-01-20 | 更新内容: 创建网络安全协议章节,包含SSL/TLS、IPSec、SSH、无线安全等详细内容 | 更新人: Assistant

被折叠的 条评论
为什么被折叠?



