Rust之恶意软件开发

2023/06/06 Rust 共 23687 字,约 68 分钟

Malware Development in Rust

RAT

RAT(远程访问工具)是指一种软件,允许操作者远程控制一个或多个系统,无论是计算机、智能手机、服务器还是联网打印机。

RAT并非总是用于攻击性操作,例如,您可能熟悉TeamViewer,它经常用于远程支持和协助(也被低技术骗子所利用)。

在攻击性安全领域,RAT应尽可能隐蔽,以避免被检测,通常使用漏洞或钓鱼进行远程安装。安装通常是一个两阶段的过程。首先,通过漏洞或恶意文档执行一个非常小的程序,称为”dropper”、”stager”或”downloader”,该程序会下载RAT本身并执行它。这种方式提高了安装过程的可靠性,并允许RAT完全从内存中运行,减少对目标系统的痕迹。

RAT的体系结构

大多数情况下,RAT由三个部分组成:

  1. 代理(Agent):代理是在目标系统上运行的恶意程序,它负责收集系统信息、执行指令、截取用户输入等。代理通常会尽可能隐蔽地运行,以避免被检测和清除。它可能会使用各种技术来隐藏自己的存在,如rootkit、进程注入等。
  2. C&C(Command and Control):C&C是远程控制服务器或控制中心,用于与代理进行通信和控制。C&C负责下发指令给代理,接收代理发送的数据和报告,并提供命令和控制接口供操作者使用。C&C通常是隐藏且安全的,以确保通信的保密性和可用性。
  3. 客户端(Client):客户端是操作者使用的控制界面,可以通过客户端与C&C进行通信和控制代理。客户端通常提供图形用户界面(GUI)或命令行界面(CLI),以便操作者可以远程执行各种操作、获取目标系统的信息、上传/下载文件等。

这种架构使得操作者可以通过C&C远程控制多个代理,并监控和操作受感染系统的活动。客户端提供了一个方便的界面,使操作者能够与C&C进行交互,并对代理进行管理和控制。这种架构允许操作者在目标系统上执行各种操作,包括监视、收集信息、执行命令、操纵文件等,同时尽可能减少对目标系统的影响和发现的风险。

Agent

代理(Agent)是RAT的有效载荷。它是在目标系统上执行的恶意软件。高级攻击平台由一个简单的代理和不同的模块组成,这些模块会动态地从内存中下载、加密和执行。这样操作人员就不需要将整个武器库部署到每个目标上,从而降低被发现或暴露能力的风险。

C2 or Server

C&C(指命令与控制,也缩写为C2) 它在攻击者控制的基础设施上操作,这些基础设施可能是先前被入侵或者专门设置的,或者如我们所见,也可以在“公共”基础设施上,比如社交网络上。一个有名的开源C&C:Merlin

Client

客户端是RAT操作者与服务器之间的接口。它允许操作者向服务器发送指令,服务器将这些指令转发给代理程序。 它可以是任何形式,可以是命令行应用程序,也可以是Web应用程序或移动应用程序。它只需要能够与服务器进行通信即可。

C&C通道与方法

仅仅使用简单的服务器作为C&C(命令与控制)中心并不能提供足够的可用性保证,因为如果服务器受到攻击或被劫持,这不仅可能泄露有关操作的详细信息,还可能使其终结。使用创造性的C&C通道可以帮助操作者规避某些检测机制:在企业网络中,向 myattack.com 发出的请求可能会显得可疑,而向 github.com 发出的请求(隐藏在许多其他请求中)则更不容易引起注意。

注:“C&C”代表“命令和控制”,“C&C 通道”是指用于命令和控制受感染系统或感染恶意软件的设备的通信通道。

Telegram

一个使用Telegram作为C&C(命令与控制)通道的机器人示例是 ToxicEye。为什么Telegram在攻击者中如此突出?首先是因为该公司的神秘感,其次是因为它无疑是最容易自动化的社交网络。

Telegram是一个提供端到端加密和各种功能的即时通讯平台,使其成为攻击者作为C&C通道的吸引人选择。Telegram在攻击者中的流行有两个主要原因。

首先,Telegram在用户隐私和安全方面赢得了声誉。Telegram背后的公司以保护用户数据和为消息提供端到端加密而闻名。这创造了一种认为通过Telegram进行的通信可能更安全,不太可能被当局或安全研究人员截获或监控的观念。

其次,Telegram提供了一个强大的机器人API,允许开发人员在平台上创建和部署机器人。机器人是自动化的账号,可以执行各种任务并与用户互动。在Telegram上轻松自动化过程和与机器人的交互,使其成为攻击者的首选。他们可以轻松设置由机器人控制的频道或群组,与被攻陷的系统或受感染的设备进行通信,促进命令和控制操作。

社交网络

其他社交网络如 Twitter(PDF)、Instagram、Youtube 等也被具有创造力的攻击者用作”无服务器”的C&C(命令与控制)中心。 代理的命令被隐藏在评论或推文中。 一方面,这样做可以隐藏在流量中。另一方面,如果你的防火墙通知你的网络服务器开始向Youtube .com 发送请求,这可能会让你感到好奇。

请注意,这里所说的”无服务器”是指利用现有平台(如社交网络)作为命令和控制的手段,而不是为此目的设置专用服务器。

DNS

使用DNS(域名系统)的优势在于,它无疑是最不容易被阻塞的协议,特别是在企业网络或公共Wi-Fi中。

DNS是互联网中用于将域名转换为IP地址的协议。攻击者可以利用DNS作为C&C(命令与控制)通道的一种方式。由于DNS是广泛使用的基础网络协议,通常不受防火墙或网络过滤的限制,因此在企业网络或公共Wi-Fi中使用DNS作为C&C通道具有一定的优势。

通过在DNS查询中嵌入命令和指令,攻击者可以通过与恶意控制的DNS服务器进行通信,实现对受感染设备或系统的控制。由于DNS查询通常是基于域名的,因此很难直接将其与恶意活动关联起来。这使得使用DNS作为C&C通道具有较低的被检测和阻止的概率,特别是在企业网络或公共Wi-Fi等受限环境中。

然而,值得注意的是,防护措施和安全设备也可以使用一些技术来检测和阻止恶意的DNS流量。此外,DNS的滥用也可能引起安全人员的怀疑,并触发进一步的调查。因此,在网络安全中,综合使用多种防御措施才能有效应对各种类型的攻击。

P2P

点对点(Peer-to-Peer,简称P2P)通信是一种架构模式,不需要服务器,而是节点(代理)直接进行通信。

在P2P通信中,参与者之间建立直接连接,彼此可以相互发送和接收数据,而无需依赖中央服务器进行中转。每个节点既是资源的请求者,也是资源的提供者,实现了分布式的通信和共享。这种去中心化的通信方式在许多场景下具有优势,例如文件共享、实时通信、区块链等。

P2P通信的优势包括:

  1. 去中心化: P2P架构不依赖于中央服务器,节点之间直接通信,使系统更具弹性和鲁棒性,避免了单点故障。
  2. 提高可扩展性: P2P通信可以随着节点的增加而扩展,节点之间的负载可以平衡分布,从而提供更好的性能和可用性。
  3. 减少网络成本: 由于节点之间直接通信,不需要额外的中转设备或服务器,降低了网络部署和维护的成本。
  4. 隐私和安全: P2P通信可以实现点对点的加密和安全传输,增加了数据隐私和安全性。

然而,P2P通信也面临一些挑战,例如网络拓扑的动态性、数据一致性的维护和网络安全等。因此,在设计和实现P2P系统时,需要考虑这些因素,并采取相应的措施来解决问题。

理论上,客户端可以连接到网络中的任何节点(称为网络的节点),发送命令,而该节点将将其传播到其他节点,直到达到预期的接收者。

实际上,由于网络约束(如NAT),网络的某些节点会被临时选为超级节点,并且所有其他节点都连接到它们。然后,操作者只需向超级节点发送指令,它们将把这些指令转发给预期的代理。由于超级节点所扮演的角色以及它们可能被对手控制的事实,这种拓扑结构中必须使用端到端加密(正如我们将在下一章中看到的)。

P2P RAT(远程访问工具)的例子包括 ZeroAccessZeus 的某些变种。

DGA

域名生成算法(Domain Generation Algorithms,简称DGA)不是一个独立的通信通道,而是一种在遭受攻击时提高C&C可用性的技术。

如果初始的C&C被关闭,代理程序会使用算法生成域名,并尝试通过这些地址联系C&C。然后,操作者只需注册其中一个域名,并将C&C迁移到该域名上。如果C&C再次被关闭,就重复这个过程。

DGA是一种反制措施,旨在对抗针对C&C的封锁或关闭。通过使用算法生成随机的域名,攻击者可以不断变化C&C的位置,使其更难被发现和封锁。这种技术使得恶意操作者可以持续地保持与被感染代理的通信,继续执行恶意活动。

然而,对抗DGA也是一项具有挑战性的任务。安全研究人员和网络安全公司会持续监测和分析DGA的行为,并采取相应的措施来检测和阻止与恶意域名相关的活动。

DGA是一种用于提高C&C可用性的技术,通过动态生成域名来绕过封锁和关闭的限制,使得恶意操作者能够持续地与被感染的代理进行通信。

外部驱动器

一些远程访问工具(RAT)和恶意软件利用外部设备,如USB闪存驱动器,来窃取数据,以针对没有互联网访问的空隔离系统。

空隔离系统是指与外部网络隔离的系统,通常是出于安全考虑而被设计为没有互联网连接的系统。这些系统通常被认为是相对安全的,因为它们与外部网络隔离,减少了遭受远程攻击的风险。

然而,通过使用外部设备如USB闪存驱动器,攻击者可以绕过网络隔离,将数据从空隔离系统中窃取出来。他们可以将恶意软件或RAT安装在受感染的外部设备上,然后将其插入目标系统中。一旦插入,恶意软件将开始窃取敏感数据,并将其保存在外部设备上。攻击者之后可以从外部设备中取回窃取的数据,并将其用于进一步的攻击或滥用。

为了保护空隔离系统免受这种类型的攻击,以下是一些建议措施:

  1. 设备管理: 管理员应限制外部设备的使用,并只允许经过授权的设备连接到空隔离系统。
  2. 安全审查: 对外部设备进行安全审查,以确保其中没有恶意软件或潜在的安全威胁。
  3. 数据加密: 对于包含敏感数据的外部设备,使用加密措施来保护数据,即使设备被窃取也能确保数据的安全。
  4. 用户教育: 向用户提供有关安全性最佳实践的培训和教育,以增强对外部设备安全风险的认识,并警惕不信任的设备。
  5. 终端防护: 在空隔离系统上使用终端防护措施,如防病毒软件和恶意软件防护工具,以侦测和阻止潜在的外部设备攻击。

通过采取适当的安全措施和策略,可以降低外部设备对空隔离系统的风险,并提供额外的安全保障。

现有的RAT

在设计自己的远程访问工具(RAT)之前,让我们先快速回顾一下现有的远程访问工具。

以下是一些常见的现有远程访问工具的例子:

  1. DarkComet: DarkComet是一个功能强大的RAT,具有多种远程控制功能,包括远程桌面、文件管理、键盘记录和远程摄像头控制等。
  2. NanoCore: NanoCore是一种高度可定制的RAT,具有持久性和隐蔽性,支持多种功能,如远程访问、键盘记录、远程文件管理和屏幕捕捉等。
  3. njRAT: njRAT是一种广泛使用的远程访问工具,具有自动扩散功能,可以通过USB设备传播。它支持远程命令执行、文件管理、远程桌面和键盘记录等功能。
  4. BlackShades: BlackShades是一种用于Windows操作系统的远程访问工具,具有远程桌面控制、远程文件管理、键盘记录和摄像头监视等功能。

这些远程访问工具被广泛用于攻击、渗透测试和远程管理等场景。它们提供了强大的功能,使攻击者能够远程控制受感染的计算机,并执行各种操作。

DarkComet

DarkComet 由法国的程序员Jean-Pierre Lesueur(也被称为DarkCoderSc)开发,在被用于叙利亚政府窃取活动人士电脑上的信息后,它变得(臭名昭著)有名。

DarkComet 最初是作为一种远程管理工具开发的,用于远程控制计算机并执行各种操作。然而,它也被一些恶意用户和组织用于非法活动,包括远程监视、窃取敏感信息和攻击目标。

特别是在叙利亚内战期间,有报道称叙利亚政府使用 DarkComet 来监视和攻击活动人士的计算机。这引起了广泛关注和谴责,使 DarkComet 成为众所周知的远程访问工具。

Meterpreter

Meterpreter(来自著名的Metasploit攻击安全套件)被其创建者定义为“一个先进的、动态可扩展的负载,使用内存中的DLL注入加载器,并在运行时通过网络进行扩展。它通过加载器套接字进行通信,并提供全面的客户端端Ruby API。它具有命令历史记录、选项卡自动完成、通道等功能”。

Meterpreter 是Metasploit框架中一种非常强大和灵活的远程访问负载(payload)。它被广泛用于渗透测试和攻击操作,用于远程控制目标系统并执行各种攻击操作。

Meterpreter 的主要特点包括:

  1. 内存注入加载器(DLL injection stagers):Meterpreter 使用内存注入技术将自身加载到目标系统的内存中,从而绕过一些防御机制,使攻击者可以在目标系统上执行恶意操作。
  2. 动态可扩展:Meterpreter 可以在运行时通过网络进行扩展,使其能够动态地加载和执行不同的功能模块。
  3. 全面的客户端端Ruby API:Meterpreter 提供了一个功能丰富的 Ruby API,使攻击者可以编写自定义的脚本和模块来执行各种操作。
  4. 命令历史记录和选项卡自动完成:Meterpreter 提供命令历史记录功能和选项卡自动完成,使操作更加方便和高效。
  5. 通道:Meterpreter 使用通道来实现与目标系统之间的双向通信,包括文件传输、远程桌面控制、键盘记录和截屏等。

Meterpreter 是 Metasploit 框架中一种功能强大的远程访问负载,具有灵活的扩展性和全面的功能。

Cobalt Strike

Cobalt Strike 是一种先进的攻击平台,专为红队开发和销售。

Cobalt Strike主要以其高级定制能力而闻名,例如其Malleable C2功能,允许操作员个性化定制C2协议,从而降低被检测到的风险。

Malleable C2是Cobalt Strike平台的一个重要特性,它允许操作员修改和自定义C2通信的行为和特征。通过使用Malleable C2,操作员可以更改C2通信的流量模式、加密方式、协议参数等,使其在网络上看起来更像正常的通信,从而降低被入侵检测系统或安全工具识别的可能性。

除了Malleable C2,Cobalt Strike还提供了其他强大的功能,如远程访问、漏洞利用、模块化的攻击框架、内网渗透、提供可视化的攻击指导等。它被广泛用于红队行动和安全评估,以模拟真实的攻击场景并评估目标系统的安全性。

Pegasus

Pegasus 是一种高级间谍软件,由以色列的公司 NSO Group 开发和销售。它被称为”远程攻击工具”(RAT),可以通过利用设备的安全漏洞,远程操控目标设备,并获取敏感信息、监视通信以及植入其他恶意软件。

这次丑闻揭示了 Pegasus 的滥用情况,许多公民和记者成为了监视目标。这引发了广泛的关注和谴责,涉及到了个人隐私、新闻自由和人权等重要议题。

设计服务器(Server)

设计RAT的服务器部分是确保整个系统运行顺利的重要步骤。下面是一些建议和指导,用于设计和实现Rust RAT服务器:

  1. 功能规划:首先,明确服务器的功能和目标。确定服务器需要处理的任务,例如接收和处理来自代理的命令、与客户端通信、数据存储等。
  2. 架构选择:选择适合项目需求的服务器架构。可以考虑使用单线程、多线程或异步处理来支持并发连接和请求。
  3. 网络通信:使用Rust的网络库(如Tokio、Actix等)来处理网络通信。选择合适的协议(如TCP或UDP)和通信机制(如WebSocket或HTTP)来实现代理和客户端与服务器之间的通信。
  4. 安全性:在设计服务器时要考虑安全性。确保使用加密协议来保护通信,验证和授权代理和客户端的连接,以及防御常见的网络攻击,如拒绝服务攻击和缓冲区溢出。
  5. 数据存储:根据需要选择合适的数据库或存储解决方案来存储和管理数据。这可能涉及存储命令、日志、代理和客户端信息等。
  6. 配置管理:设计一种灵活的配置管理机制,使服务器可以根据需求进行配置调整。这可以包括定义命令和功能、设置连接参数、配置日志记录等。
  7. 异常处理:实现适当的错误处理和异常处理机制,以确保服务器在面对异常情况时能够稳定运行。
  8. 日志记录:添加适当的日志记录功能,以便跟踪和分析服务器的行为。这有助于故障排除、安全审计和性能优化。
  9. 安全审计:定期进行安全审计,检查服务器的安全性并修复潜在的漏洞和弱点。
  10. 测试和验证:在部署服务器之前进行全面的测试和验证。测试服务器的各种功能和场景,以确保其稳定性和可靠性。

通信协议

在之前列举的各种通信渠道中,选择HTTP(S)通道将在80%的情况下表现出色,并且只需投入20%的努力。

事实上,HTTP协议很少被阻断,而且作为Web的基础,已经有无数成熟的实现可供使用。

如果你决定不使用HTTP(S)而是实现自己的协议,最终你将得到与HTTP相同的功能(请求-响应、流式传输、传输加密、元数据),但是实现可能不完善、不可靠,并且没有数百万(或更多?)人工时投入到Web生态系统中的工作。

因此,HTTP(S)通道是一个理想的选择,它提供了广泛的支持和成熟的工具,可以满足大部分需求,并且具有良好的可靠性和安全性。当然,具体选择还要根据项目的需求和约束进行评估,但在大多数情况下,HTTP(S)是一个强大且高效的通信渠道。

实时通讯

在使用HTTP进行实时通信时,有四种主要的方法可以实现:

  1. 短轮询(Short Polling):客户端通过发送HTTP请求来轮询服务器,以获取实时数据的更新。服务器会立即响应,无论数据是否有更新。如果没有新数据可用,客户端会再次发送请求以继续轮询。
  2. WebSockets(WS):WebSockets是一种基于TCP的双向通信协议,它允许在客户端和服务器之间建立持久连接。一旦建立连接,服务器和客户端可以通过发送消息来实时交换数据。相比于短轮询,WebSockets具有更低的延迟和更高的效率,适用于实时性要求较高的应用程序。
  3. 服务器推送事件(Server-Sent Events,SSE):SSE允许服务器向客户端推送数据流,而无需客户端发起请求。通过建立一条持久的HTTP连接,服务器可以不断地向客户端发送更新的数据。这种方式适用于单向通信场景,其中服务器是数据的唯一来源。
  4. 长轮询(Long Polling):长轮询是一种改进的轮询技术,在没有新数据可用时,服务器不会立即响应客户端的请求,而是保持连接打开一段时间,直到有新数据可用或超时。这种方式可以减少不必要的轮询请求,但仍然会增加服务器负载。

选择适当的实时通信方法取决于应用程序的需求和特点。WebSockets 通常被认为是最强大和高效的实时通信协议,但如果应用程序只需要单向通信或低频率的更新,SSE 或长轮询也可以是合适的选择。短轮询则更适合于简单的应用程序,对实时性要求不高的场景。

短轮询

第一种实时通信方法是短轮询(Short Polling)。在这种情况下,客户端向服务器发送请求,服务器立即回复。如果没有新数据可用,响应为空。而且大部分情况下都是如此。因此,服务器的响应大部分时间都是空的,本可以避免发送这些空响应。

因此,短轮询在网络和CPU方面都是浪费的,因为每次都需要解析和编码请求。唯一的好处是它没有更简单的方法了。

尽管短轮询简单直接,但它的效率不高,并且会导致不必要的网络开销和资源消耗。对于实时通信的需求,其他的方法如WebSockets、Server-Sent Events或长轮询可能更为适合,可以减少请求次数和资源浪费,提供更高效的实时通信体验。

WebSockets

WebSockets 是一种双向数据流。客户端建立与服务器的连接后,它们可以相互发送数据。

使用 WebSockets 时会遇到许多问题。首先,它需要保持大量的连接,其中许多连接处于空闲状态,这在服务器资源方面是一种浪费。其次,它没有自动重新连接机制,每当发生网络错误(例如客户端从 Wi-Fi 切换到 4G),您都必须实现自己的重新连接算法。第三,它没有内置的身份验证机制,因此通常需要通过握手和其他自定义协议来进行身份验证。

如果需要最小化网络使用和延迟,那么 WebSockets 是一个不错的选择。WebSockets 的主要缺点是实现的复杂性。从请求/响应的范式转向数据流不仅在理解和代码组织上很困难,而且在基础设施方面也很困难(例如如何配置反向代理)。

SSE

与 WebSockets 相反,Server-Sent Events (SSE) 流是单向的:只有服务器可以向客户端发送数据。此外,自动重新连接机制通常已内置到客户端中。

与 WebSockets 类似,SSE 需要保持大量的连接处于打开状态。

SSE 的缺点是在服务器端实现不容易。

相对于 WebSockets,SSE 提供了一种简单的服务器向客户端推送数据的方式,而无需客户端发起请求。这对于实时通知、事件推送等场景非常有用。然而,SSE 的功能有限,只能由服务器向客户端发送数据,无法实现双向通信。

长轮询

长轮询(long polling):客户端发送一个请求,并附带上它所拥有的最新数据的指示(例如时间戳),服务器只有在有新数据可用或经过一定时间后才发送响应。

长轮询的优点是非常简单易实现,因为它不是一个流式的通信方式,而是一个简单的请求-响应模式。它非常健壮,不需要自动重新连接,并且能够优雅地处理网络错误。与短轮询相比,长轮询在资源使用方面也更加高效。

唯一的缺点是相对于 WebSockets,它在延迟方面不那么快速,但对于我们的使用场景并不重要(如果我们设计实时游戏,则会更加重要)。

在 Rust 中,长轮询非常高效,与许多其他编程语言相比。事实上,由于使用异步(async),每个打开的连接只使用很少的资源(一个简单的异步任务),而许多语言使用整个操作系统线程。

此外,正如我们将在后面看到的,实现对长轮询请求进行优雅关闭非常容易(与 WebSockets 或 SSE 相比)。

由于长轮询只是简单的 HTTP 请求,它是一种在某些激进的防火墙或网络设备中最有可能不被阻止的技术。

构建 Rust Web

在设计Web应用程序时,有许多模式可供选择。其中一个著名的模式是罗伯特·C·马丁的”Clean Architecture”。

这种架构将项目分成不同的层次,以创建独立于框架的系统,具有以下特点:

  1. 独立于框架:该架构不依赖于某个库或功能丰富的软件的存在。这使得您可以将这些框架视为工具,而不必将系统塞入它们的限制之中。
  2. 可测试性:业务规则可以在没有UI、数据库、Web服务器或任何其他外部元素的情况下进行测试。
  3. 独立于UI:UI可以轻松更改,而不影响系统的其他部分。例如,可以将Web UI 替换为控制台UI,而不需要更改业务规则。
  4. 独立于数据库:可以将Oracle或SQL Server等数据库切换为Mongo、BigTable、CouchDB或其他数据库。业务规则不受数据库的限制。
  5. 独立于任何外部机构:实际上,您的业务规则对外部世界一无所知。

“Clean Architecture” 对于非专业架构师来说可能过于复杂,其中的术语只有专业架构师才能理解,并且包含了过多的抽象层。对于实际编写代码的人来说可能并不适用。

此处采用另一种方法,同样灵活但更简单,并且适用于传统的服务器端渲染的Web应用程序和JSON API。

View层:负责前台页面的表示

展示层负责请求的反序列化和响应的序列化。 它拥有自己的模型(HTML 模板或需要编码为 JSON/XML 的结构)。它封装了有关编码 Web 服务器响应的所有细节。 展示层调用服务层。

Service层:(业务层 )控制业务

服务层是业务逻辑所在的地方。我们应用程序的所有规则和不变性都存在于服务层。 需要验证电话号码?但电话号码的格式是什么?这个问题的答案在服务层。 创建代理工作时需要进行哪些验证?这是服务层的职责。

Entity层:(实体层 )数据库在项目中的类

实体层封装了服务层将使用的所有结构。每个服务都有自己的实体组。 为什么不称之为模型?因为模型通常指的是持久化在数据库中或由表示层发送的对象。除了令人困惑外,在现实世界中,并不是所有的实体都被持久化。例如,表示具有其用户的组的对象可以在您的服务中使用,但既不持久化也不由表示层传输。 在我们的情况下,实体将是 Agent(代理)和 Job(工作)(工作是由客户端创建的命令,由服务器存储和分派,并由代理执行)。

DAO层(Repository):(持久层)主要与数据库进行交互

存储库层是对数据库的简化抽象。它封装了所有与数据库的交互。 存储库层由服务层调用。

Controler层(Drivers):(控制层 )控制业务逻辑

驱动程序封装了对第三方API的调用和与外部服务(如电子邮件服务器或块存储)的通信。 驱动程序只能被服务层调用,因为这里才是业务逻辑的所在。

Web框架

hyper 是 Rust 中成熟的 HTTP 库。但对于我们的用例来说,它有点太底层了。

actix-web 是 Rust 的新兴 Web 框架之一。它专注于绝对速度,并且是最早采用 async/await 的 Web 框架之一。不幸的是,它的发展历程被一些争议所困扰,原始创作者决定离开。现在该项目的开发已经停滞不前。

warp 是在 hyper 基础上构建的 Web 框架,由同一位作者开发。它小巧、可靠,并且对于99%的项目来说足够快速。不过,它的 API 稍显奇怪。从函数式编程的角度来看,它非常可组合,使用过滤器来实现,但它完全不符合传统 Web 框架的思维模型(请求、服务器、上下文)。尽管如此,它仍然易于理解和使用。

tide 是我认为最优雅的 Web 框架。不幸的是,它依赖于 async-std 运行时,因此无法与使用 tokio 作为异步运行时的项目一起使用(或会产生奇怪的副作用)。 最后,还有 gotham,它与 warp 类似,也是基于 hyper 构建的,但似乎提供了更好的 API。不过,这个库仍处于早期阶段,并没有(据我所知)有关其在生产环境中广泛使用的报告。

由于我们追求简单易用和稳健性,并且需要与 tokio 运行时兼容,我们将选择使用 warp

Library

Database

数据库访问层有三个主要的候选库:diesel 、 tokio-postgres 、 sqlx。

diesel 是一个安全、可扩展的 Rust ORM(对象关系映射)和查询构建器。它是我使用的第一个数据库库。不幸的是,有两个因素使得这个库不是理想的选择。首先,它是一个ORM,意味着它在数据库之上提供了一个抽象层,可能需要时间来学习,它是特定于该库的,难以掌握。其次,它提供了同步接口,这意味着调用是阻塞的,正如我们在第三章中所看到的,它可能在主要是异步的应用程序中引入微妙且难以调试的错误,比如一个Web服务器。

tokio-postgres 它是异步的。不幸的是,它过于底层,无法提高生产效率。它要求我们自己进行所有的反序列化操作,这可能会引入很多bug,因为它消除了Rust提供的类型安全性,特别是当我们的数据库模式发生变化时(数据库模式总是会发生变化)。

sqlx 除了提供异步API外,它还提供了类型安全性,极大地降低了引入bug的风险。但这个库更进一步:通过其 query! 宏,查询可以在编译时(或测试时)与数据库的模式进行检查。

所以,基于性能、异步支持和类型安全性的考虑,推荐使用 sqlx 作为数据库访问层的库。

Logging

在攻击性安全的背景下,日志记录是一项繁琐的任务。实际上,如果你的C&C服务器被入侵或被查获,日志可能会透露很多关于你的目标以及被窃取的数据的信息。

因此,我建议不要记录每个请求,而是仅为了调试目的记录错误,并非常小心地不要记录有关你的目标的数据。

日志记录对于调试和故障排除非常重要,但在敏感的安全环境中,必须谨慎处理日志,并避免记录敏感信息。要确保仅记录必要的错误信息,而不记录与目标有关的数据。此外,应采取适当的安全措施来保护日志文件,例如加密、访问控制和定期审查。

设计代理(Agent)

设计代理程序时尽可能小巧。

最受欢迎的库存在一个问题,它们往往非常庞大,并不适用于我们的使用场景。

为了实现尽可能小的代理程序,我们可以考虑以下几个方面:

  1. 选择轻量级的网络库:选择一个专注于性能和轻量级的网络库,而不是使用那些功能繁多的大型库。这样可以减小代理程序的体积,并提高性能。
  2. 精简功能:根据实际需求,仅保留代理程序所需的功能,去除不必要的模块和功能。这有助于减小代码体积并简化程序结构。
  3. 优化依赖项:审查代理程序的依赖项,并选择那些体积较小且性能良好的库。避免引入过多的依赖项,以减小程序的整体大小。
  4. 使用编译时优化:利用Rust语言的编译时优化功能,例如使用适当的编译标志和优化级别,以减小生成的可执行文件的大小。
  5. 资源管理:合理管理代理程序所使用的资源,包括内存、网络连接等,以避免资源浪费和不必要的负载。

通过以上措施,我们可以设计一个尽可能小巧的代理程序,以满足我们的需求。在追求小巧的同时,仍需确保代理程序具备足够的功能和安全性。

HTTP library

在 crates.io 上搜索 HTTP 客户端库时,我们会找到以下几个选择:hyper 、 reqwest 、 awc (Actix Web Client) 、 ureq 、 surf。

最适合我们代理程序需求(小巧、易于使用和正确性)的是 ureq。

ureq 是一个简单、轻量级的 HTTP 客户端库,它专注于提供基本的 HTTP 请求功能,适合于我们设计的代理程序。它具有简单直观的 API,易于上手和集成到我们的代码中。

相比其他库,ureq 不依赖于复杂的异步运行时,这使得它更适合我们设计的小型代理程序。它的轻量级设计有助于减小代理程序的体积,并提供了所需的基本功能。

总的来说,ureq 是一个符合我们需求的简单、小巧、易于使用的 HTTP 客户端库,可以满足我们代理程序的要求。

端到端加密

理解密码学是与技术和尤其是安全相关的任何重要事物的先决条件。从信用卡到加密货币,再到安全的即时通讯工具、密码管理器和互联网本身,密码学无处不在,并在数字世界中提供了安全性,使得几乎可以无限制地传输和复制任何信息成本几乎为零。

端到端加密被认为是通信安全的圣杯,因为它是我们最接近模拟现实生活通信的方式。在一次对话中,只有受邀的人才能加入圈子并参与讨论。任何入侵者都会很快被驱逐出去。端到端加密提供了同样的保证,只有受邀的参与方才能听取对话并参与其中。但正如我们将看到的,它也增加了复杂性,并不是绝对安全的。

端到端加密通过在通信的两端使用加密算法,确保在传输过程中,只有发送方和接收方能够解密和读取数据。中间的任何中间人,包括服务提供商或网络攻击者,都无法获得明文数据。这种加密技术为通信提供了更高的隐私和安全性,防止了窃听和篡改攻击。

然而,端到端加密并非没有缺点。它增加了通信过程的复杂性,包括密钥交换、身份验证和密钥管理等方面。此外,端到端加密只能保证端点之间的安全,而不能保证通信中的其他环节的安全。因此,在实现端到端加密时,仍然需要综合考虑其他安全措施,如防止恶意软件、网络攻击和物理访问等。

端到端加密提供了重要的通信安全保障,但需要认识到它的复杂性和局限性。在实际应用中,需要综合考虑各种因素,并采取适当的安全措施来保护通信的机密性和完整性。

C.I.A三角模型

为了确保在网络通信中的机密性、完整性和可用性,信息安全领域引入了C.I.A三角模型,即保密性(Confidentiality)、完整性(Integrity)和可用性(Availability)。这个模型被广泛应用于信息安全的规划、实施和评估。

  1. 保密性(Confidentiality):保密性是指确保信息只能被授权的人或实体访问和阅读,防止未经授权的披露或泄露。在互联网通信中,保密性的实现可以通过使用加密技术,如端到端加密,以确保只有发送方和接收方能够解密和读取数据。
  2. 完整性(Integrity):完整性是指确保信息在传输或存储过程中不被篡改、修改或损坏。保持信息的完整性意味着任何未经授权的修改都会被检测到,并且接收方能够验证接收到的信息与发送方发送的信息完全一致。实现完整性可以使用数字签名、消息认证码等技术来验证信息的完整性。
  3. 可用性(Availability):可用性是指确保信息在需要时可供合法用户访问和使用,防止服务中断或不可用。保持可用性意味着网络和系统要能够持续运行,提供稳定和及时的服务。为了确保可用性,需要采取措施来防止网络攻击、硬件故障、自然灾害等造成的服务中断。

C.I.A三角模型提供了一种综合的方法来评估和实施信息安全控制措施。通过确保保密性、完整性和可用性,可以提高通信和数据的安全性,并降低信息被未授权访问、篡改或丢失的风险。在设计和实施网络应用、通信协议和数据存储时,必须综合考虑C.I.A三角模型的各个方面,以确保信息的安全性和隐私保护。

保密性

保密性是指对私密或敏感信息进行保护,防止未经授权的访问。它的对立面是披露(disclosure)。

在信息安全领域,保密性是确保只有授权人员或实体能够访问和获取敏感信息的原则和措施。这意味着仅允许授权用户或实体获得敏感信息的权限,以防止未经授权的人员获得访问权。保密性的目标是确保信息只能被需要知道的人或组织访问,并防止信息泄露、盗取或被滥用。

保密性的实现可以通过多种技术和措施,包括加密、访问控制、身份验证和身份验证等。加密是一种常用的保密性技术,通过对敏感信息进行加密,即将信息转换为不可读的形式,只有授权用户才能解密并获得原始信息。访问控制是另一个重要的保密性措施,它确保只有经过授权的用户可以访问特定的敏感信息或系统资源。

保密性的重要性在于保护个人隐私、商业机密和敏感数据。通过实施适当的保密性措施,可以防止敏感信息的不当披露、盗窃或滥用,从而维护个人权利、商业竞争力和信息安全。

完整性

完整性是指保护数据免受未经授权的篡改。它的对立面是篡改(alteration)。

在信息安全领域,完整性是确保数据在传输、存储或处理过程中不被非授权方进行任何未经授权的更改或篡改的原则和措施。完整性的目标是确保数据的准确性、一致性和可信性,以防止数据被恶意篡改或损坏。

实现数据完整性的关键是保护数据的完整性,防止数据在传输、存储或处理过程中被非授权的修改或篡改。常见的保护完整性的方法包括使用加密技术、使用校验和和哈希函数来验证数据的完整性,以及实施访问控制和身份验证措施来防止非授权方对数据进行修改。

数据完整性对于确保数据的可信性、一致性和可用性非常重要。通过保持数据的完整性,可以确保数据在传输、存储和处理过程中保持不变,防止恶意篡改、损坏或破坏数据的完整性。这对于各种领域,包括金融、医疗、电子商务和个人隐私等都至关重要。

可用性

可用性是指信息始终能够被可靠地访问和使用。它确保系统、服务或数据在需要时可供用户使用,而不受任何干扰或限制。

在信息安全领域,可用性是确保系统、服务或数据持续可用的原则和措施。它涉及到预防和减少可能导致中断或停止访问的各种因素,包括硬件或软件故障、电力中断、自然灾害、攻击或人为错误等。

保证可用性的关键是识别和解决单点故障,并提供冗余和备份措施。这包括使用冗余服务器、备份数据、实施负载均衡和故障转移机制,以确保即使在某些组件或系统发生故障时,仍然能够提供连续和可靠的访问。

拒绝访问是可用性的对立面,它指的是未经授权的拒绝访问或限制对信息、系统或服务的正常访问。可用性的目标是确保信息和服务始终可用,并及时恢复任何中断或故障,以满足用户的需求和预期。

在信息安全和系统设计中,可用性是一个重要的方面,尤其是对于关键系统和服务。保持系统的高可用性可以增强用户体验、确保业务连续性,并提供可靠的服务。

威胁建模

威胁建模是对潜在风险和攻击向量进行系统分析,以制定针对这些威胁的防御和对策的过程。它是发现在系统中可能发生的问题以及针对谁和什么进行防御的艺术。

根据《威胁建模宣言》,在最高层次上,当我们进行威胁建模时,我们要回答四个关键问题:

  1. 我们正在做什么?
  2. 可能发生什么问题?
  3. 我们将采取什么措施来应对?
  4. 我们的工作是否做得足够好?

威胁建模必须在项目的设计阶段进行,它可以确定需要采取风险缓解措施的问题。通过威胁建模,我们可以识别潜在的威胁和漏洞,并采取适当的措施来减轻和防止潜在的攻击。这有助于提高系统的安全性和可靠性,并确保在设计和开发过程中考虑到安全性。

密码学

密码学,或称为加密学(源自古希腊语:kryptós,“隐藏,秘密”;以及graphein,“写作”,或-logia,“研究”),是在存在称为对手的第三方的情况下进行安全通信的技术和研究的实践。

换句话说,密码学是与可信方共享机密信息的科学和艺术。

当听到(或阅读)密码学这个词时,加密肯定是你首先想到的东西,但正如我们将看到的那样,加密并不是确保系统安全所需的唯一操作。密码学还涉及其他类型的操作。

原语和协议

密码学 的基本构建块是原语(primitives),它们就像乐高积木一样。原语是构建密码学算法的基本组件。

一些原语的例子包括SHA-3、Blake2b和AES-256-GCM。

协议(protocols)则是将这些原语组合起来,以确保应用程序的安全性。它们就像由乐高积木搭建的房屋。

一些协议的例子包括TLS、Signal和Noise。这些协议利用原语来实现数据的加密、认证和安全传输。

Hash

哈希函数(Hash functions)接受任意长度的消息作为输入,并产生固定长度的哈希值。相同的消息将产生相同的哈希值,而不同的消息应该永远不会产生相同的哈希值。

哈希函数在验证文件完整性方面非常有用,而无需比较或传输整个文件。

你可能在下载页面上遇到过哈希函数。

一些哈希函数的例子包括SHA-3、Blake2b和Blake3。此外,还有MD5和SHA-1,但由于这些函数存在现实世界中的攻击,因此不应再使用它们。

MAC

消息认证码(MAC,Message Authentication Code)函数是哈希函数和秘密密钥的组合。

秘密密钥用于身份验证:只有知道秘密密钥的参与方才能生成有效的身份验证哈希(也称为标签或代码)。

MAC也被称为带密钥的哈希。

MAC的一个示例用途是JSON Web Tokens(JWT):只有知道秘密密钥的服务器才能发行有效的令牌。

KDF

密钥派生函数(KDF,Key Derivation Function)允许从一个不太安全的源生成一个密钥。

KDF通常用于从密码或其他低熵源派生加密密钥。它们应用密码学变换来增强派生密钥的安全性,使其更适用于密码操作。

一些KDF的示例包括PBKDF2(基于密码的密钥派生函数2)、bcrypt和scrypt。这些函数增加了计算复杂性,并结合盐值以防止暴力破解和彩虹表攻击。

KDF在需要强大且安全的密钥的情况下非常重要,但可用的源材料可能不符合所需的安全标准。

有两种类型的密钥派生函数:

第一种类型接受低熵输入,如密码、口令或大数字,并产生高熵、安全的输出。它们也被称为基于密码的密钥派生函数(PBKDF)。例如,Argon2d和PBKDF2。

第二种类型接受高熵输入,并产生同样高熵的输出。例如:Blake2b。

需要注意的是,像Blake2b这样的函数是多功能的,你也可以将其用作具有秘密密钥的MAC函数。

区块加密法

将消息(也称为明文)和一个秘密密钥输入到区块加密中,它会输出一个加密的消息(也称为密文)。在给定相同的秘密密钥的情况下,你可以解密密文以恢复原始消息,两者在位上完全相同。大多数情况下,密文与明文的大小相同。

AES-CBC 是一个分组密码的示例。

AEAD

大多数情况下,在加密消息时,还想要对密文进行认证,此时就诞生了认证加密算法。

它们可以被看作是先加密再进行消息认证(MAC),以及先验证消息认证码(MAC),然后再解密的组合过程。

给定明文、秘密密钥和可选的附加数据,该算法将生成带有认证标签的密文(通常附加在密文后面)。在解密过程中,给定密文、相同的秘密密钥和相同的附加数据,如果密文或用于解密的附加数据出现错误(被修改),算法将在尝试解密数据之前失败并返回错误。

与先加密再进行消息认证相比,认证加密具有以下优点:它只需要一个密钥,并且更容易使用,从而降低了通过混合不同基元引入漏洞的可能性。

带有附加数据的认证加密也被称为 AEAD(Authenticated Encryption with Additional Data)。

如今,当你需要加密数据时,AEAD是(普遍)推荐的解决方案。

为什么呢?

想象一下,Alice想要使用预先安排的秘密密钥向Bob发送加密消息。如果Alice使用了简单的区块加密,那么在传输过程中,加密的消息可能会被拦截、修改(仍然保持加密形式),并被修改后传输给Bob。当Bob解密该消息时,他将无法意识到消息已被篡改。

当Bob解密密文时,可能会产生无意义的数据!完整性(记住C.I.A三要素)被破坏了。

再举一个例子,想象一下你想要将加密的钱包金额存储在数据库中。如果你不使用关联数据,那么恶意的数据库管理员可以交换两个用户的金额,而这将不会被察觉到。然而,通过使用认证加密,你可以使用用户ID作为关联数据,减轻加密数据交换的风险。

而使用 AEAD,附加数据的认证标签将防止篡改,并在解密时进行验证,确保接收方能够确定消息的完整性和真实性。

总而言之,AEAD提供了同时加密和认证数据的强大功能,确保数据的机密性和完整性。

非对称加密

非对称加密,又称为公钥加密。 其原理很简单。加密密钥以成对的形式存在:

  • 公钥是应该与他人共享的密钥,他们可以使用该密钥来加密发送给你的数据,只有你能够解密。
  • 私钥是一种绝密的密钥,不应该与任何人分享,它允许你解密之前使用公钥加密的数据。 私钥和公钥的组合被称为密钥对(keypair)。

与区块加密等对称加密相比,非对称加密的优势在于公钥的交换非常容易。可以将公钥放在网站上等地方进行共享。 在实际应用中,非对称加密并不直接使用,而是使用一系列的协议结合了认证加密、密钥交换和签名算法的混合使用。

Diffie–Hellman密钥交换

迪菲-赫尔曼密钥交换(更常被称为密钥交换)是一种通过公共通道在两个参与方之间建立共享密钥的方法。

通过Alice的公钥和Bob的私钥,与通过Bob的公钥和Alice的私钥计算得到的共享密钥是相同的。因此,Alice和Bob都可以使用各自的私钥和对方的公钥计算出相同的共享密钥。 现如今,推荐使用的密钥交换函数是椭圆曲线迪菲-赫尔曼(ECDH),相比RSA加密,它更简单实现。

然而,通过ECDH密钥交换计算得到的共享密钥不能直接用于对称加密。大多数AEAD算法需要一个均匀随机的对称密钥,而共享密钥并不具备这种特性。因此,为了“增加它们的熵”,我们将密钥交换函数的输出传递给密钥派生函数(KDF),以生成可以用于对称加密的共享密钥。

最著名且被广泛使用的密钥交换算法:x25519。

Signatures

签名是与MAC相对应的非对称加密方式:给定一个密钥对和一条消息(由私钥和公钥组成),私钥可以生成该消息的签名。公钥可以用来验证该签名确实是由具备私钥知识的某个人(或某个实体)签发的。

就像所有的非对称算法一样,公钥是可以安全共享的,并且正如我们之后将会看到的那样,签名算法的公钥大多数情况下是数字(加密)身份的基础。 (无特殊要求的情况下)最著名且最常用的签名算法是:ed25519。

端到端加密

端到端加密(End-to-End Encryption,E2EE)是一种协议家族,其中只有通信的用户才拥有用于加密和签名消息的密钥。

公钥加密

公钥加密算法在加密和解密方面都是相对慢速的,而且有消息长度限制。因此,仅仅使用公钥加密是无法完全保障通信安全的。

为了解决这个问题,端到端加密通常结合了对称加密算法和公钥加密算法。对称加密算法可以快速加密大量数据,而公钥加密算法则用于安全地交换对称密钥。

具体而言,下面是端到端加密的一般流程:

  1. 发送方生成一个随机的对称密钥,用于加密消息。
  2. 发送方使用接收方的公钥加密对称密钥,并将其与加密后的消息一起发送给接收方。
  3. 接收方使用自己的私钥解密收到的对称密钥,然后使用解密后的对称密钥解密消息。

通过这种方式,对称加密算法提供了快速且高效的加密,而公钥加密算法用于安全地交换对称密钥,确保只有接收方能够解密消息。

总结起来,端到端加密综合使用了对称加密和公钥加密,以实现安全的通信。这种方式能够保护通信内容的隐私性和完整性,并确保只有预期的接收方能够解密和读取消息。

混合加密

混合加密(Hybrid encryption)综合了对称加密和非对称加密的优点,实现了更好的安全性和效率。具体而言,混合加密的过程如下:

  1. 发送方生成一个随机的对称密钥(称为临时对称密钥),用于加密消息。对称加密算法通常具有快速、高效的特点,并且可以加密任意长度的消息。
  2. 发送方使用接收方的公钥加密临时对称密钥,并将其与加密后的消息一起发送给接收方。非对称加密算法用于安全地交换临时对称密钥。
  3. 接收方使用自己的私钥解密收到的临时对称密钥,然后使用解密后的对称密钥对消息进行解密。

通过这种方式,混合加密既保留了对称加密的快速、高效特点,又利用非对称加密的安全性来交换对称密钥。每个消息使用一个临时对称密钥进行加密,确保消息的长度不受限制,并能以最大速度进行加密和解密。

然而,尽管混合加密提供了更好的安全性和效率,但仍存在一些问题。例如,为了提供良好的安全性,RSA 密钥的长度通常较大(3072 位或更多),而且 RSA 加密本身并不容易实现正确(主要与填充相关),这也是导致错误的一个主要来源。

因此,在选择混合加密方案时,需要仔细考虑密钥的长度和算法的实现细节,以确保安全性和可靠性。

Diffie–Hellman 密钥交换

终端到终端加密(End-to-End Encryption,简称E2EE)并不仅仅是密钥交换和认证加密(AEAD)的简单组合。E2EE的目标是确保只有预期的接收方能够解密和阅读消息,即使通信经过中间人。

除了密钥交换和认证加密之外,E2EE通常涉及以下要素:

  1. 公钥基础设施:E2EE依赖于使用公钥进行加密和数字签名验证。公钥在用户之间共享,用于建立安全的通信通道。公钥基础设施(PKI)提供了管理和验证公钥的机制,包括使用数字证书。
  2. 信任和身份认证:E2EE依赖于对公钥的真实性和完整性的信任。用户需要验证接收到的公钥是否属于预期的接收方,并且未被篡改。建立信任和验证身份是E2EE的关键方面。
  3. 密钥管理:E2EE需要安全的密钥管理实践来保护私钥。私钥应该被安全地存储,免受未经授权的访问。如果私钥泄漏或受到威胁,可能会导致过去、现在和未来消息的解密。有效的密钥管理实践包括密钥轮换、安全存储和必要时的密钥吊销机制。
  4. 前向保密:E2EE通常采用前向保密技术,即使私钥泄漏,也不应该能够解密先前的加密消息。前向保密通过为每个会话或消息交换生成临时密钥来实现。这样,即使私钥泄漏,也无法用于解密先前的通信。

确实,管理密钥可能具有挑战性,E2EE的安全性在很大程度上依赖于正确的密钥管理实践。密码学家和安全专家强调安全的密钥存储、强大的密钥生成算法和定期的密钥轮换,以减轻与密钥泄漏相关的风险。

总体而言,E2EE是一个复杂的过程,涉及多种密码技术,并需要密钥管理和信任的慎重考虑。它旨在为端到端通信提供强大的保密性和完整性保证,即使存在中间人或潜在的密钥泄漏,也能保护用户的隐私。

前向保密

前向保密(Forward Secrecy),也被称为完美前向保密,是密码学中通讯协议的一种安全特性,指的是长期使用的主密钥泄漏不会导致过去的会话密钥泄漏。确保如果某个密钥在某个时刻T泄露,那么在此之前发送的消息(T-1、T-2、T-3等)无法被解密。

实现前向保密性的一种方法是创建许多密钥对,每个消息使用一个密钥对,消息接收后将其删除。但是这样做会导致我们失去”一个公钥等于一个身份”的特性,我们需要验证每个公钥是否合法,实际上来自于Bob而不是中间人攻击者,这是不切实际的。

幸运的是,有更有效的方法来实现前向保密,例如使用临时密钥交换密钥对。这些密钥对针对每个会话或消息进行生成,并在使用后丢弃。通过使用临时密钥对,用于加密和解密的共享密钥对于每个会话都是唯一的,提供了前向保密而不损失身份方面。

通过这种方式,即使某个密钥泄露,也能实现前向保密,而无需持续验证公钥,从而实现安全高效的通信,而不会危及过去的消息。

签名

签名允许拥有私钥的人对文档或消息进行身份验证。通过对消息或文档进行签名,私钥所有者确认其有效性。然后,所有具有公钥访问权限的人都可以验证签名与文档是否匹配。 因此,签名是构建数字身份的理想工具。

在加密通信中,签名与加密结合使用可以提供以下安全保障:

  1. 身份验证:通过对消息进行签名,发送方可以验证其身份。接收方使用发送方的公钥来验证签名,确保消息是由预期的发送方发送的,而不是被篡改或冒充的。
  2. 完整性保护:签名还可以用于保护消息的完整性。接收方可以使用发送方的公钥验证消息的签名,如果签名不匹配,表明消息可能被篡改过。
  3. 防止抵赖:由于签名是基于私钥进行的,私钥的持有者无法抵赖曾经签署过的消息。这意味着在需要验证消息的来源和完整性时,签名可以提供强有力的证据。

通过将签名和加密结合使用,我们可以实现机密性、身份验证和完整性保护的全面安全通信。

需要注意的是,签名仅验证消息的来源和完整性,并不提供消息的机密性。因此,在保护通信内容的同时,仍然需要使用加密算法来确保消息的保密性。

总结起来,使用签名和加密相结合的方式可以为我们的通信提供身份验证、完整性保护和防止抵赖等安全保障。这种组合使得我们能够确保消息的真实性和完整性,并建立可靠的数字身份。

端到端加密

现代端到端加密 = 签名 + 密钥交换 + AEAD

签名是长期的身份密钥,用于签署临时密钥交换密钥。

临时密钥交换密钥用于加密对称的AEAD密钥。

AEAD密钥用于加密消息。

密码学的常见问题和陷阱

加密中常见的问题和陷阱包括:

  1. 密钥管理极其困难:安全地生成、存储、传输和更新密钥是加密系统中的重要挑战。错误的密钥管理可能导致密钥泄露、数据丢失或安全漏洞。
  2. 尽量使用认证加密:认证加密提供了数据完整性和机密性的保护。使用经过充分验证和安全的认证加密算法,例如AES-GCM、ChaCha20-Poly1305等。
  3. 谨慎使用公钥加密:公钥加密算法(例如RSA、ElGamal)通常比对称加密算法更复杂且更容易出错。正确使用公钥加密需要理解密钥管理、填充方案和安全性假设等方面的细节。
  4. 不要自行实现加密原语:加密算法和协议的设计与实现需要深入的专业知识和经验。自行编写加密代码容易引入漏洞,因此应该使用经过广泛评估和验证的加密库和工具。
  5. 在消费者硬件上的大规模加密可能不可靠:消费者硬件通常具有资源限制和性能限制,这可能导致加密操作的效率和安全性受到影响。在设计和实施加密方案时,需要考虑硬件能力和性能限制。

加密是一个复杂而关键的领域,需要严谨的设计、实施和管理。对于非专业的加密实现者来说,最好依赖经过审查和广泛使用的加密工具和标准,以减少潜在的安全风险。

密钥管理

在密钥管理方面存在以下挑战:

  1. 密钥生成和存储:生成强大的随机密钥,并安全地存储它们是至关重要的。不恰当的密钥生成方法或不安全的存储方式可能导致密钥的泄露。
  2. 密钥分发:确保安全地将公钥分发给通信方是关键问题。中间人攻击和伪造公钥的风险需要得到有效管理和防范。
  3. 密钥更新和撤销:定期更新密钥以及及时撤销不再需要的密钥是维护密钥管理的重要方面。密钥的泄露、失效或失误可能需要进行紧急的更新和撤销操作。
  4. 密钥保护和访问控制:确保只有授权人员能够访问密钥,并采取适当的措施保护密钥免受未经授权的访问和攻击。

虽然有一些已经存在的解决方案和最佳实践,但密钥管理仍然是一个具有挑战性的领域,需要持续的研究和创新。保持密钥的安全性和机密性是确保加密系统的强大安全性的关键因素之一。

使用经过身份验证的加密

使用认证加密是非常重要的。传统的块密码和消息认证码(MAC)可能存在一些问题和安全漏洞。

现在,应当使用已被广泛接受并被认为是安全的认证加密算法,例如AES-256-GCM、Chacha20-Poly1305或XChacha20-Poly1305。这些算法结合了加密和认证的功能,能够提供更强大的安全性保障。

AES-256-GCM是一种块密码模式,使用256位的密钥和Galois/Counter Mode(GCM)提供了加密和认证功能。Chacha20-Poly1305是一种流密码算法与Poly1305认证算法结合,同样提供了加密和认证的功能。XChacha20-Poly1305是Chacha20-Poly1305的扩展版本,使用更长的96位随机数作为输入,提供了更高的安全性。

这些认证加密算法已经被广泛采用和研究,被认为是安全可靠的选择。然而,正确的使用和实现仍然非常重要。密钥的生成、使用和管理需要遵循最佳实践,并结合适当的密钥长度和安全性参数,以确保加密系统的强大安全性。

避免自实现加密

自行实现密码学原语(primitives)是一项困难但可行的任务。虽然可以通过单元测试和集成测试来验证其正确性,但仍存在许多潜在的危险。

自行实现密码学原语可能面临以下问题:

  1. 侧信道泄露(side-channel leaks):密码学原语的实现可能受到侧信道攻击,通过观察实际的执行时间、功耗或其他物理特性,攻击者可能获得有关密钥或数据的敏感信息。
  2. 非常量时间编程(non-constant time programming):密码学原语的实现需要注意时间复杂度的一致性,以避免泄露有关密钥或数据的信息。非常量时间编程可能导致侧信道攻击的风险。
  3. 其他安全性问题:除了侧信道攻击和非常量时间编程之外,还存在许多其他可能使您的代码在实际使用中不安全的因素。这可能包括缺乏对不同攻击的防御机制、未处理的边界条件或异常情况等。

因此,为了确保安全性和可靠性,通常建议使用经过广泛审查和验证的密码学库或框架,而不是自行实现密码学原语。这些库和框架经过了专业的安全审计和测试,并采用了最佳实践来防止常见的安全漏洞。使用这些库可以减轻开发人员在设计和实现安全的加密协议时的负担,并提供更可靠的保护。

大规模加密操作可能不可靠

在消费者硬件上进行大规模的加密操作可能会面临一些不可靠性的挑战。

在加密算法中,即使发生单个位翻转,也会对输出产生全面的影响,这是设计上的特点。无论是电气或磁性干扰、宇宙射线(这也是太空计算系统具有大量冗余的原因之一)还是其他干扰,都可能破坏加密应用程序的状态,特别是在使用扩展或块链式的算法时,这可能是极为严重的问题。

对此,可以采取一些对策来增加可靠性,其中之一是使用ECC(Error Correcting Code)内存。ECC内存可以检测和纠正n位内存错误,从而提高系统对内存错误的容错能力。通过使用ECC内存,可以在一定程度上减少由于位翻转等硬件错误导致的加密操作失败的风险。

除了使用ECC内存,还可以考虑其他冗余和错误检测机制,如备份和恢复算法、校验和、哈希校验等,以增加系统的鲁棒性和可靠性。

确保在消费者硬件上进行大规模的加密操作的可靠性是一个重要的挑战,但通过采用适当的冗余和错误检测机制,可以降低硬件错误对加密应用程序的影响,并提高系统的可靠性和安全性。

TOFU

如前所述,密钥分发很困难。 我们以 Signal 等安全通讯应用为例:你可以发送消息给任何人,即使你尚未验证过他们的身份密钥,因为你可能无法当场亲自验证收信人的二维码。

这种模式被称为首次使用信任(TOFU):你相信由 Signal 服务器发送给你的公钥是合法的,而不是恶意的。 然后,你可以选择手动验证密钥(通过扫描二维码或比对数字),但这不是继续会话所必需的。

TOFU 在默认情况下是不安全的,但仍提供了安全性和可用性之间的最佳折衷方案,这对于大规模采用加密技术的人群来说是必需的。

Rust密码学生态系统

Rust 密码学生态系统包括了许多优秀的密码学库,这些库在内存安全性和性能方面都有显著的改进。使用Rust实现密码学算法能够减少内存安全问题,并提供高性能的加密功能。这对于构建安全可靠的系统至关重要。

sodiumoxide

sodiumoxide 是 libsodium的Rust 包装器,libsodium 是大多数应用密码学家推荐的著名C密码库。

这个库的缺点是,由于它是C绑定,可能会引入难以调试的错误。 此外,请注意,原始维护者在2020年11月宣布他将退出该项目。尽管如此,在当前状态下,该项目相当稳定,任何紧急问题(如果有的话)肯定会被及时修复。

ring

ring 专注于实现、测试和优化一组核心的加密操作,通过易于使用(难以误用)的API进行暴露。ring 提供了Rust API,并使用Rust、C和汇编语言的混合编写。

ring 为高级协议和应用程序提供了低级原语。该项目的主要维护者以其对密码学的认真态度和高质量的代码而闻名。 唯一的问题是一些算法,如 XChaCha20-Poly1305,目前还没有实现。

dalek cryptography

dalek-cryptography是一个GitHub组织,汇集了关于纯Rust椭圆曲线密码学的多个项目,如x25519和ed25519。

这些项目被一些对密码学非常认真的组织使用,比如Signal和Diem。

Rust Crypto

Rust Crypto是一个GitHub组织,汇集了你在纯Rust中需要的所有密码学原语,大多数情况下通过为所有不同的算法提供一个基本trait并为其实现来完成(比如查看aead)。

但并非所有的crate都经过专业的第三方审计。

rustls

rustls是一个用Rust编写的现代TLS库。它在底层使用ring进行密码学操作。它的目标是只提供安全可用的功能,例如仅支持TLS 1.2及以上版本。

Other

还有许多其他的crate,比如blake3,但是在我看来,只有在上述的crate/组织中找不到你需要的原语时,才应该考虑使用它们。

文档信息

Search

    Table of Contents