菜单

加密

相关源文件

本文档概述了 Shadowsocks Windows 客户端中使用的加密系统。它涵盖了加密框架、支持的加密方法以及在代理操作期间数据如何加密和解密。有关系统代理配置的详细信息,请参阅系统代理配置

概述

Shadowsocks 依赖加密来保护客户端和服务器之间的流量。加密系统由一个模块化框架组成,支持多种加密算法,包括流密码和带关联数据的认证加密(AEAD)密码。该系统设计为可扩展的,允许轻松添加新的加密方法。

加密实现基于通过 P/Invoke 访问的本机加密库构建,并通过抽象层来为应用程序的其余部分维护一个清晰的接口。

来源: shadowsocks-csharp/Encryption/EncryptorFactory.cs1-88 shadowsocks-csharp/Encryption/IEncryptor.cs1-15

加密框架架构

加密系统采用分层架构,具有通用接口和工厂模式用于实例化。IEncryptor 接口定义了所有加密实现必须遵循的契约。EncryptorBase 抽象类提供了通用功能,而具体的实现则处理不同的加密算法。

来源: shadowsocks-csharp/Encryption/IEncryptor.cs1-15 shadowsocks-csharp/Encryption/EncryptorBase.cs1-97 shadowsocks-csharp/Encryption/EncryptorFactory.cs1-88

本机加密库

Shadowsocks 使用本机加密库来高效实现加密。这些库通过 .NET 的 P/Invoke 访问。

主要的本机库是 libsscrypto.dll,它为 AEAD 和流密码提供加密操作。该库在运行时动态加载,并通过处理 P/Invoke 调用的包装类进行访问。

来源: shadowsocks-csharp/Encryption/Sodium.cs1-113 shadowsocks-csharp/Encryption/MbedTLS.cs1-109

加密器工厂

EncryptorFactory 负责根据指定的方法和密码创建相应的加密器实例。它维护一个支持的加密方法及其对应实现类的注册表。

在静态初始化期间,工厂会注册来自不同提供程序的所有可用加密方法:

  1. AEADOpenSSLEncryptor
  2. AEADSodiumEncryptor
  3. AEADMbedTLSEncryptor
  4. PlainEncryptor(用于未加密连接)

当多个实现支持相同的密码时,工厂会优先选择更安全的实现。例如,如果 libsodium 和 MbedTLS 都支持 AES-256-GCM,则工厂在可用时将优先选择 libsodium 实现。

来源: shadowsocks-csharp/Encryption/EncryptorFactory.cs10-87

支持的加密方法

Shadowsocks Windows 客户端支持多种加密方法,分为两大类:

AEAD 密码

AEAD(带关联数据的认证加密)密码提供机密性和认证性。它们通常比流密码更安全。

密码密钥大小(字节)盐值大小(字节)随机数大小(字节)标签大小(字节)
aes-128-gcm16161216
aes-192-gcm24241216
aes-256-gcm32321216
chacha20-ietf-poly130532321216
xchacha20-ietf-poly130532322416

流密码

流密码一次加密一个字节的数据。虽然通常速度更快,但它们不提供认证。

密码密钥大小(字节)IV 大小(字节)
aes-128-ctr1616
aes-192-ctr2416
aes-256-ctr3216
aes-128-cfb1616
aes-192-cfb2416
aes-256-cfb3216
camellia-128-cfb1616
camellia-192-cfb2416
camellia-256-cfb3216
chacha20-ietf3212
rc4-md51616
salsa20328

来源: shadowsocks-csharp/Encryption/EncryptorBase.cs3-59 shadowsocks-csharp/Encryption/EncryptorFactory.cs18-54

加密过程流

数据在加密系统中以下列方式流动:

  1. 客户端应用程序将数据发送到 TCPRelay 组件
  2. TCPRelay 从 EncryptorFactory 请求加密器
  3. 加密器使用指定的方法和密码加密数据
  4. 加密数据发送到 Shadowsocks 服务器
  5. 对于传入数据,使用 Decrypt 方法逆转该过程

来源: shadowsocks-csharp/Encryption/IEncryptor.cs5-13 shadowsocks-csharp/Encryption/EncryptorFactory.cs57-71

AEAD 加密详情

AEAD 密码提供认证加密,这意味着它们可以检测加密消息是否被篡改。Shadowsocks 根据 SIP004 规范实现 AEAD 密码。

AEAD 加密过程遵循以下步骤:

  1. 密钥派生:使用 HKDF(基于 HMAC 的密钥派生函数)从密码派生出子密钥
  2. 盐值生成:为每个连接生成一个随机盐值
  3. 分块加密:数据被分割成块,每个块使用唯一的随机数进行加密
  4. 认证:每个块包含一个认证标签以验证完整性

对于 UDP 数据包,使用更简单的过程,因为每个数据包都是独立处理的。

来源: shadowsocks-csharp/Encryption/Sodium.cs66-95 shadowsocks-csharp/Encryption/MbedTLS.cs86-106

流加密详情

流密码将数据加密为连续的字节流。该过程包括:

  1. 密钥派生:使用 MD5 从密码派生出密钥
  2. IV 生成:为每个连接生成一个随机初始化向量 (IV)
  3. 加密:使用派生密钥和 IV 加密数据
  4. 拼接:IV 在传输前被预置到加密数据的前面

流密码通常比 AEAD 密码快,但由于不认证加密数据,因此安全性较低。

来源: shadowsocks-csharp/Encryption/Sodium.cs97-111 shadowsocks-csharp/Encryption/MbedTLS.cs58-81

库初始化

在进行任何加密操作之前,必须初始化本机加密库。这会在应用程序启动时自动发生。

Sodium 类将嵌入的 libsscrypto.dll 解压到临时位置并进行初始化。在初始化期间,它还会检查硬件加速 AES-256-GCM 支持的可用性,这会影响首选哪种实现。

来源: shadowsocks-csharp/Encryption/Sodium.cs14-55 shadowsocks-csharp/Encryption/MbedTLS.cs14-35

安全考量

Shadowsocks Windows 客户端的加密系统在保证性能的同时优先考虑安全性:

  1. 首选 AEAD 密码:由于额外的安全性,推荐使用 AEAD 密码而不是流密码
  2. 硬件加速:系统检查并利用可用的硬件加速
  3. 实现选择:当密码有多种实现可用时,选择最安全或最有效的
  4. 向后兼容性:虽然支持旧方法,但鼓励使用新方法

建议使用诸如 aes-256-gcmchacha20-ietf-poly1305 等 AEAD 密码,以获得安全性和性能的最佳平衡。

来源: shadowsocks-csharp/Encryption/EncryptorFactory.cs18-30 shadowsocks-csharp/Encryption/Sodium.cs22-51

与其他组件的集成

加密系统与 Shadowsocks Windows 客户端的其他组件集成

加密系统主要由 TCPRelay 和 UDPRelay 组件用于加密和解密客户端与服务器之间的流量。ShadowsocksController 协调这些组件的配置和初始化。

来源: shadowsocks-csharp/Encryption/IEncryptor.cs5-13 shadowsocks-csharp/Encryption/EncryptorFactory.cs57-71