首页 > 解决方案 > 使用 tiny-AES-c 进行加密无线链路

问题描述

我最近发现了 C 中用于嵌入式系统的 AES 实现,并一直在考虑在无线点对多点链接(或初学者的点对点)中使用它。

代码在我的平台上正确编译,当使用 CTR 模式提供的测试代码时,它似乎给出了正确的结果,背靠背(这个 CRT 模式是我需要的,因为我的数据包每个 120 字节并且不能更改)。

本质上,发送方 Tx 应该使用 tiny-AES 加密功能来生成每个 120 字节的连续加密数据包流,将它们与附加的 CTR 和标头等一起发送,并在另一端由接收方 Rx 接收和解密.

设想发送器 Tx 和接收器 Rx 使用完全相同的 tiny-AES 代码和相同的密钥,只有我知道。该密钥可以设置,并且在不同的 Tx-Rx 对上会有所不同。

我的问题特别涉及 CRT 模式以及在 Tx 和 Rx 上使用以下功能:

/* Initialize context calling (iv can be NULL): */
void AES_ctx_init(AES_ctx *ctx, uint32_t keylen, const uint8_t *key, const uint8_t *iv);

/* ... or reset IV or key at some point: */
void AES_ctx_set_key(AES_ctx *ctx, uint32_t keylen, const uint8_t *key);
void AES_ctx_set_iv(AES_ctx *ctx, const uint8_t *iv);

所以

  1. 目的是什么?这是否AES_ctx_init()只在安全链接的加密/解密会话开始时执行一次?
  2. 该功能的目的是什么AES_ctx_set_iv(),再次,这是否只在安全链接会话开始时完成一次?评论“......或在某个时候重置 IV 或密钥”对我来说不清楚 - 我的问题的原因......那是在 CRT 模式下使用 AES 时什么时候需要重置 IV?
  3. Tx 和 Rx 是否需要使用相同的 IV,是否可以保持原样,或者是否需要在每个新的安全链路会话中进行更改?我了解通常会为 Tx/Rx 对选择密钥,并且仅在需要时由用户在两者上进行修改,但通常每个会话都会保持相同。这通常正确吗?IV是这种情况(或不是),在什么时候重置IV?

在无线链路中,由于噪声的原因,如果没有实施 FEC,接收器将因 CRC 错误而被迫丢弃数据包。在我的链接中,将验证接收到的 120 字节数据包的 CRC(一一接收),如果 CRC 正确,则启动解密以恢复原始数据,但如果不正确,则丢弃数据。这对加密的 Tx 数据包流有什么影响,因为它们继续传输,因为没有握手协议告诉 Tx Rx 由于 CRC 错误(如果有的话)而丢弃了一个数据包?

如果这些问题的答案以有关 tiny-AES 的一些进一步文档的形式存在,我将不胜感激,因为提供的注释假设人们已经熟悉 AES 等。


因此,这里对已经发表的评论/回复有进一步的了解。基本上,Tx / Rx 对具有预定义的数据包结构,其中包含特定的有效负载、标头 CRC 等,但我们称其为“数据包”。有效负载是我需要加密的,它固定为 120 字节,无论如何都不可协商,它在数据包中。所以你的意思是,每次传输数据包时,Tx 和 Rx 都需要更改每个数据包的随机数,并且 Tx 和 Rx 需要在每次处理数据包时使用相同的随机数?

假设我开始传输,并且有数据包(1),数据包(2)......数据包(n)等。然后对于每个传输的数据包,我需要更新“计数器”,并且发送器和接收器都需要同步,以便两者在会话中使用相同的随机数?

如果由于噪声或干扰,Tx/Rx 系统可能会失去同步,并且不知何故,nonce 的两个独立计数器不再同步并且可以说在同一页面上,这可能会出现问题……一般来说,一个会话平均不需要超过 2^16 个数据包,所以你能找到解决方法吗?正如我所说,为每个单独的数据包发送不同的随机数是完全不可能的,因为有效负载已经完整且完整。

如果这可行,我认为也许你可以阐明的另一种方法是通过 GPS。假设每个 Tx 和 Rx 都有一个 GPS 模块(就是这种情况),那么时间信息可以从 Tx 和 Rx 上的 GPS 时钟中获取,因为两者都将独立接收,并且某种同步计数器可能会滚动到更新两者的随机数,比如在一个会话中从 0 计数到 2^16……你同意吗?因此,即使由于噪声/干扰,数据包被接收器丢失,计数器也会在后台使用某种形式的可靠“tick”继续更新随机数……</p>

关于熵的来源,很明显,lampert 电路将为本地运行的良好 PRNG 提供此功能,例如 2^16 个数据包的会话,但这在我的系统上尚不可用,但如果我们决定更进一步……</p>

作为该领域的专业人士,您对此有何看法?问候,

标签: encryptionaes

解决方案


我假设您所指的 Tiny AES 是tiny-AES-c(尽管您的代码与该代码略有不同;我找不到任何AES_ctx_set_key定义的地方)。我假设当您说“CRT 模式”时,您的意思是 CTR 模式。

AES_ctx_init() 的目的是什么,这是否只在安全链接的加密/解密会话开始时执行一次?

这会初始化内部数据结构。具体来说,它执行密钥扩展,从主密钥创建必要的轮密钥。在这个库中,它看起来会在会话开始时调用一次,以设置密钥和 IV。

在 CTR 模式下,绝对不能在两条不同的消息上重复使用 Key+Nonce (IV) 组合是绝对关键的。(CTR 模式在技术上没有“IV”。它有一个“nonce”,但它看起来完全像一个 IV,并且在我见过的每个加密库中都以相同的方式传递。)如果你需要重用 nonce,您必须更改密钥。这通常意味着您必须在加密设备上保留一个持久(即跨系统重置)运行计数器,以跟踪最后使用的随机数。有多种方法可以安全地使用半随机随机数,但您需要高质量的熵源,这在嵌入式设备上通常不可用。

如果将 NULL 作为 IV/nonce 传递并重用密钥,CTR 模式几乎是毫无价值的加密方案。

由于您需要能够干净地丢弃数据包,因此您需要做的是将随机数与每个数据包一起发送。随机数不是秘密。对于给定的键,它必须是唯一的。nonce 是 16 个字节长。如果数据太多,常用的方法是在会话开始时交换 nonce 的前 12 个字节,然后使用底部 4 个字节作为计数器,从 0 开始。如果会话可以长于 2^32块,那么您需要在用完值后重置会话。

请记住,这里的“块”长 16 个字节,每个块都需要自己的随机数。为了适应 120 字节,您可能会执行类似发送 4 字节起始计数器之类的操作,然后为 n、n+1、n+2、... n+6 添加 7 个块。

设计这个井有点复杂,很容易做错并破坏你的密码学。如果这很重要,您可能应该聘请有经验的人为您设计这个。我做这种工作,但我相信你能找到很多人。


所以你的意思是,每次传输数据包时,Tx 和 Rx 都需要更改每个数据包的随机数,并且 Tx 和 Rx 需要在每次处理数据包时使用相同的随机数?

正确的。Tx 端将确定 nonce,Rx 端将消耗它。尽管他们可以以某种方式协调而不是明确发送它,只要它永远不会重复,并且他们总是同意。这是 CTR 模式的好处之一;它依赖于不一定要发送的“计数器”。

时钟很好,因为它不重复。棘手的部分是保持同步,同时绝对确定你不会重复使用 nonce。如果每个 nonce 的时间窗口很大,则更容易保持同步。如果时间窗口很小,确保您永远不会重复使用 nonce 会更容易。将时钟派生的随机数与顺序计数器结合起来可能是一个好方法。接收方仍然存在持续的同步问题,接收方需要尝试几个不同的计数器(或随机数+计数器)来找到正确的计数器。但这应该是可能的。

请注意,同步假设有一种方法可以区分有效的明文和无效的明文。如果明文有结构,那么您可以尝试一个随机数,如果输出是乱码,请尝试另一个。但是如果明文没有结构,那么你就有一个大问题,因为你将无法同步。我所说的“结构”是指“你能分辨出有效数据和随机噪声之间的区别吗?

使用时钟,只要您的窗口足够小以至于您永远不会重复使用起始随机数,即使在重置时,您也可以避免需要 PRNG。随机数不必是随机的;它永远不会重复。

请注意,如果您有一个 4 字节的计数器部分,那么您有 2^32 个块,而不是 2^16。


推荐阅读