物联网安全基础知识 - 第 1 部分:加密技术的使用

作者:Stephen Evanczuk

投稿人:DigiKey 北美编辑

编者按:本系列文章由多个部分组成,文中将提供一些实用的指导,以帮助开发人员确保从一开始就遵循相关的最佳实践。第 1 部分(本文)探讨底层安全设计的加密算法。第 2 部分探讨私钥、密钥管理和安全存储在系统安全中所起的作用。第 3 部分检查安全处理器的内建机制,以缓和企图破坏物联网设备上系统和应用软件执行的威胁。第 4 部分明确并展示如何在高级处理器中应用安全机制,帮助确保进行必要的隔离,以缓解对物联网设备运行时环境进行的攻击。第 5 部分介绍如何在将物联网设备连接到物联网云资源时,通过采用更高级别安全措施,让这些设备实现持续的物联网安全。

在工业、医疗、运输及其他关键应用中,对物联网应用的依赖程度迅速增加,这极大地改变了安全格局。以往,企业应用普遍拥有随时可用的资源来处理安全算法,但如今企业级物联网应用却饱受威胁日益增多之苦,且其攻击目标是不断扩大的资源受限型物联网设备网络。企业在急于迎接快速涌现的物联网机遇时,部署的物联网设备在功能上往往无法支持基本的安全措施,因此难以保护存储的数据,且无法保证在易受攻击的网络上进行数据和命令交换。

当然,开发人员需要做到什么程度才能确保设计安全取决于多个因素。每个应用都面临着各自的威胁,因而需要对这些威胁带来的风险进行适当的评估。由于互连设备面临的威胁数量不同以往,任何物联网设备都至少需要一些最低限度的安全措施。

在一些人看来,为简单的物联网设备实施强大的安全措施似乎是过度设计,但即使是简单的温度传感器,如果缺乏足够的保护,也会成为黑客入侵企业网络的切入点[1]。其实,正因为物联网应用提供了普遍连接性,而这些应用却基于资源受限的设备,才导致物联网安全持续面临挑战。事实上,即使物联网设备设计提供足够的资源在软件中执行加密算法,但只要这些算法在实现过程中存在细微错误,应用仍然可能易受攻击。

本文介绍了加密算法的基本类别,并探讨了它们在安全方面的作用。然后,本文将向开发人员展示如何利用 Maxim IntegratedMicrochip TechnologyTexas Instruments 提供的旨在加速这些算法的处理器和专用器件,以在简化实现的同时增强安全性的不同方面。

各种类型的加密算法及其作用

加密算法可分为三大类,涉及机密性、身份验证(验证消息来源)、不可抵赖性(证明发送方创建了加密或签名的消息)和完整性等基本安全原则:

  • 对称密钥算法,即算法或加密法使用相同的密钥,将人类可读的(明文)消息加密为受保护的版本(密文),之后再将密文解密为明文。对称密钥加密法通常用于确保机密性。常见的对称加密算法包括:
    • Triple DES(一种数据加密标准),又称为 3DES,或由美国国家标准与技术研究院 (NIST) 正式命名的三重数据加密算法 (TDEA)。
    • 高级加密标准 (AES)[2] 算法,例如使用 256 位密钥的 AES-256。
  • 非对称密钥算法,即加密法使用一组成对的私钥和公钥对消息进行加密和解密,通常作为密钥协议和数字签名安全扩展协议的一部分。非对称加密法通常用于确保机密性、身份验证或不可抵赖性。公钥加密算法包括:
    • 使用有限域加密 (FFC) 的算法,包括:
      • 联邦信息处理标准 (FIPS) 数字签名算法 (DSA)
      • 互联网工程任务组 (IETF) Diffie-Hellman (DH)[3] 密钥交换
    • 使用整数分解加密 (IFC) 的算法,包括:
      • Rivest-Shamir-Adleman (RSA)[4] 算法
    • 使用椭圆曲线加密 (ECC) 的算法,包括:
      • 椭圆曲线 Diffie-Hellman (ECDH)[5] 密钥交换
      • 椭圆曲线数字签名算法 (ECDSA)[6]
  • 哈希算法,此算法将原始消息缩减为一个很短且长度固定的唯一值,常称为哈希值、摘要或签名。这种单向转换函数在验证消息是否遭到窜改(完整性)方面扮演重要角色,可应用于涉及消息验证码 (MAC)、密钥哈希消息验证码 (HMAC) 或密钥派生函数 (KDF) 等的多种协议。加密哈希算法包括:
    • 消息摘要 5 (MD5)
    • 安全哈希算法 (SHA)[7],例如将消息转换成 256 位哈希值的 SHA-256。

与所有有效的加密算法一样,上述算法的设计也需遵循多个关键要求,本文碍于篇幅,无法详细列出。但从广义角度来看,基于密钥的算法需要生成的密文几乎无法在无密钥的情况下解密(至少从经济角度来说不可行)。哈希算法必须快速生成哈希值:将相同的输入消息转换成相同的哈希值,但对于哪怕只是有细微变化的输入消息,也要生成截然不同的哈希值;并且,绝不会将两条不同消息转换成相同的哈希值,也不会因给定了特定的哈希值而生成原始消息。

尽管这些算法及其他加密算法在细节上有极大差异,但都仰赖一系列专门设计的低级操作、转换和其他数学运算,以便达成整体目标。例如,AES 加密法使用一系列“回合”将明文转换为密文,每个“回合”都会由用户原始密钥产生唯一的“回合密钥”,并将其与原矩阵合并(清单 1)。

副本
Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)]) 
begin 
   byte  state[4,Nb]
 
  state = in
 
   AddRoundKey(state, w[0, Nb-1])
 
    for round = 1 step 1 to Nr–1
        SubBytes(state)
        ShiftRows(state)
        MixColumns(state)
        AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) 
    end for 
 
    SubBytes(state)
    ShiftRows(state)
    AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) 
 
    out = state
end

清单 1:这段伪代码说明了消息加密中涉及的操作序列,此序列使用一组由发送方私钥派生的值 (w),将明文 (in) 转换为密文 (out)。(代码来源:NIST)

在一个回合中,SubBytes() 转换使用替换表 (S-box) 替换每个字节,替换表本身也是一系列转换的结果(图 1)。

SubBytes() 阶段使用替换表 (S-Box) 替换每个字节的示意图图 1:在 AES 加密法中,SubBytes() 阶段使用替换表 (S-Box) 替换每个字节。(图片来源:NIST)

在序列的下一步中,ShiftRows() 转换将后三行中的字节移位,且每行移动不同的字节数(图 2)。

AES 加密法执行序列中 ShiftRows() 阶段示意图图 2:AES 加密法执行序列中的 ShiftRows() 阶段通过增加偏移量来对行进行移位。(图片来源:NIST)

在序列的最后步骤中,MixColumns() 对每一列进行转换,用多项式的结果替换列中的每个字节;然后 AddRoundKey() 使用专为此目的创建的回合密钥,与各混合列中的字节进行按位异或 (XOR) 运算以转换结果。

回合总数因密钥大小而异。AES-128 使用 128 位密钥,需要 10 个回合,而 AES-192(密钥大小为 192 位)及 AES-256(256 位)分别需要 12 和 14 个回合。解密遵循相同的模式,只是反向执行各过程步骤及其各自的转换。

用于密钥交换的 ECDH 和用于数字签名的 ECDSA 等最新加密法依赖于更复杂的数学运算,例如由以下公式广泛定义的椭圆曲线代数结构:

等式 1 公式 1

通过慎重选择曲线参数 ab 并使用其他约束条件,该曲线将显示出有用的加密属性(同样,本文无法详述)。虽然概念简单,但特定的参数组合至关重要:曲线参数选择不当会导致算法仍然无法抵御复杂的攻击。为了帮助消除这种可能性,NIST 提供了一组具有强鲁棒性的标准加密曲线,包括 P-192、P-224、P-256 和鲁棒性更强的其他曲线。曲线名称与曲线的底层素域中元素的素数 p 的位长相对应。

开发人员可使用这些属性结合 ECDSA,利用确定的曲线对部分消息进行签名,并将公钥和签名(一对标示为 rs 的数字)提供给接收方。实际的签名过程包含以下步骤:

  • 首先,算法在曲线上选取某个点,称为基点 G(x,y),再将基点与开发人员的私钥 (d) 模 p 相乘,以生成公钥 Q(x,y)

公式 2 公式 2

  • 然后,在值域 [1 ... n-1] 中选取随机数 k 以产生另一个坐标点 (x1,y1)

公式 3 公式 3

  • 这样,即可生成消息 m 的 SHA 哈希值 H(m)
  • 最后,使用随机数 k 的模逆元 k-1,生成数字签名的最终 rs 分量,如下所示:

公式 4 公式 4

公式 5 公式 5

最终结果可以互换,用于验证消息、确认消息完整性,并确保不可抵赖性。

如何实现加密算法

一般浅略了解这些算法后,人们都会发现加密算法依赖于一连串数学运算,并且计算量相当庞大,想要快速完成运算根本不可能或不切实际,因此入侵者无法加以利用。此外,即使粗略地查验每种算法也能看出,在不影响设备主要功能要求的情况下,资源受限的物联网设备几乎不可能执行算法的软件实现。最后,由本文未详述的算法具体细节可知,即便是细微的编码错误或对标准稍有误解,也可能造成安全漏洞,甚至会让加密过程彻底失效。

即使是最大的开发机构和极度依赖这些算法的应用,也可能会在算法实现时出错。例如,某游戏主机就曾发生过一次众所周知的安全漏洞事件,原因就是在实施 ECDSA 时,该公司在公式 3 所示的计算类型中使用了常数 k,而非随机数,结果让黑客推导出安全密钥 d。类似的安全漏洞事件也曾造成比特币严重损失,就是因为使用了有缺陷的随机数发生器来产生 k

将基于硬件的加密功能内置到处理器和专用安全 IC 中,开发人员就可在很大程度上忽略执行加密算法的复杂细节,而将精力集中在使用这些功能来保护应用的优势上。在器件内集成数据流和运算,额外增加了一重安全保护,从而消除了一种常见的攻击形式,即监视外部总线以寻找特权信息迹象。除了提供特定算法的可靠实现外,基于硬件的解决方案还允许开发人员在设计中整合安全功能,而不会影响基本要求,如传输响应延迟和影响整体性能。

这些器件内置的加密加速器可为主处理器分担加密执行任务,使其能够集中处理设计的主要功能。实际上,基于硬件的加密支持已逐渐成为处理器的常见功能。同时,并非每个应用都需要用到上述算法所支持的所有安全措施。其实,在许多处理器中,开发人员都能找到多种加速加密算法和算法组合,例如以下处理器:

  • Maxim Integrated 的 MAX32631 32 位微控制器,支持 AES 和 DSA 加密
  • Maxim Integrated 的 MAX32520 32 位 MCU,支持 AES、SHA 和 ECDSA 算法
  • Microchip Technology 的 PIC 24F XLP 16 位微控制器系列,其中 PIC24FJ256GA406 等器件支持 AES 和 3DES 加密
  • Microchip Technology 的 32 位 PIC 32MZ MCU 和 32 位 SAM9X60 MPU 系列,其中 PIC32MZ2048EFM144SAM9X60T 等器件支持 AES 和 3DES 加密,以及 SHA 和 HMAC 哈希函数
  • Texas Instruments 的 SimpleLink MCU 系列,如 CC1312RCC2652R 无线 MCU,支持 AES、ECDH 和 ECDSA 加密,以及 SHA 哈希函数

Maxim Integrated 的 DS28E38 和 Microchip Technology 的 ATECC608A 等其他安全器件,集成了加密加速器和加速身份验证协议所需的相关功能。除了丰富的加密功能之外,这些器件还支持前文所述的 ECDSA 运算。在物联网设备或智能外设中,主机处理器可使用此类身份验证 IC 来快速创建 ECDSA P-256 数字签名,以发送至另一台设备,或者验证来自其他设备的 ECDSA P-256 签名。

支持安全功能的处理器与专用器件,通常使用广泛的基于硬件的安全框架构建,以便提供高质量随机数发生器等额外的安全功能。许多提供此级别功能的器件会运用半导体设计中固有的随机噪声源,使真随机数发生器 (TRNG) 所需的熵最大化。正如前文所述的比特币示例所表明,这类 TRNG 是正常运算加密算法的必要因素。

集成对私钥和其他机密数据安全存储的支持,是安全设计最重要的功能之一。此外,这些处理器及其他类似处理器更具备其他架构性功能,可提供更深层的安全支持。

鉴于其所有功能,具有集成加密加速器和相关功能的处理器,可通过使用简单的应用程序编程接口 (API) 库来简化安全设计的开发。直观的 API 函数调用让开发人员可以依靠 API 来访问基础硬件功能,从而使安全实现抽象化。例如,开发人员可以使用 Maxim Integrated 推出的用于 MAX32520 MCU 的 MAX32520-KIT 评估套件,结合该公司的 Micros 软件开发套件 (SDK),可快速构建安全的物联网设备。除了相关的驱动程序和中间件之外,Maxim Integrated 的 Micros SDK 还包括示例函数,这些函数演示了使用 AES 加密法加密 (AES128_ECB_enc()) 和解密 (AES128_ECB_dec ()) 消息所需的基本设计模式(清单 2)。

副本
int AES128_ECB_enc(int asynchronous)
{
    printf( asynchronous ? "Test Cipher Async\n" : "Test Cipher Sync\n");
 
    char *_key = "797f8b3d176dac5b7e34a2d539c4ef36";
    char key[MXC_AES_KEY_128_LEN];
    ascii_to_byte(_key, key, MXC_AES_KEY_128_LEN);
 
    const char *iv_src = "";
    char iv_dst[16];
    ascii_to_byte(iv_src, iv_dst, 16);
 
    char *_pt= "00000000000000000000000000000000";
    char pt[MXC_AES_DATA_LEN];
    ascii_to_byte(_pt, pt, MXC_AES_DATA_LEN);
 
    mxc_ctb_cipher_req_t cipher_req = {
        (uint8_t*)pt,
        MXC_AES_DATA_LEN,
        (uint8_t*)iv_src,
        (uint8_t*)result,
        &Test_Callback };
 
    // Reset crypto block
    MXC_CTB_Init(MXC_CTB_FEATURE_CIPHER | MXC_CTB_FEATURE_DMA);
    MXC_CTB_IntEnable(asynchronous);
 
 
    MXC_CTB_Cipher_SetMode(MXC_CTB_MODE_ECB);
    MXC_CTB_Cipher_SetCipher(MXC_CTB_CIPHER_AES128);
    MXC_CTB_Cipher_SetKeySource(MXC_CTB_CIPHER_KEY_SOFTWARE);
 
    // Load key into cipher key register
    MXC_CTB_Cipher_SetKey((uint8_t *)key, MXC_AES_KEY_128_LEN);
 
    if (asynchronous){
        wait = 1;
        MXC_CTB_Cipher_EncryptAsync(&cipher_req);
        while( wait );
    } else {
        MXC_CTB_Cipher_Encrypt(&cipher_req);
    }
    const char *_expected = "322FD6E503395CDB89A77AC53D2B954F";
    char expected[MXC_AES_DATA_LEN];
    ascii_to_byte(_expected, expected, MXC_AES_DATA_LEN);
 
    return AES_check(result, expected, MXC_AES_DATA_LEN);
 
}
 
int AES128_ECB_dec(int asynchronous)
{
    printf( asynchronous ? "Test Cipher Async\n" : "Test Cipher Sync\n");
 
    char *_key = "797f8b3d176dac5b7e34a2d539c4ef36";
    char key[MXC_AES_KEY_128_LEN];
    ascii_to_byte(_key, key, MXC_AES_KEY_128_LEN);
 
    const char *iv_src = "";
    char iv_dst[16];
    ascii_to_byte(iv_src, iv_dst, 16);
 
    char *_pt= "322FD6E503395CDB89A77AC53D2B954F";
    char pt[MXC_AES_DATA_LEN];
    ascii_to_byte(_pt, pt, MXC_AES_DATA_LEN);
 
    mxc_ctb_cipher_req_t cipher_req = {
        (uint8_t*)pt,
        MXC_AES_DATA_LEN,
        (uint8_t*)iv_src,
        (uint8_t*)result,
        &Test_Callback };
 
    // Reset crypto block
    MXC_CTB_Init(MXC_CTB_FEATURE_CIPHER | MXC_CTB_FEATURE_DMA);
    MXC_CTB_IntEnable(asynchronous);
 
 
    MXC_CTB_Cipher_SetMode(MXC_CTB_MODE_ECB);
    MXC_CTB_Cipher_SetCipher(MXC_CTB_CIPHER_AES128);
    MXC_CTB_Cipher_SetKeySource(MXC_CTB_CIPHER_KEY_SOFTWARE);
 
    // Load key into cipher key register
    MXC_CTB_Cipher_SetKey((uint8_t *)key, MXC_AES_KEY_128_LEN);
 
    if (asynchronous){
        wait = 1;
        MXC_CTB_Cipher_DecryptAsync(&cipher_req);
        while( wait );
    } else {
        MXC_CTB_Cipher_Decrypt(&cipher_req);
    }
    const char *_expected = "00000000000000000000000000000000";
    char expected[MXC_AES_DATA_LEN];
    ascii_to_byte(_expected, expected, MXC_AES_DATA_LEN);
 
    return AES_check(result, expected, MXC_AES_DATA_LEN);
}

清单 2:开发人员可以检查 Maxim Integrated 的 Micros SDK 分发包中的示例代码,以学习使用 MAX32520 MCU 的集成加密函数执行 AES 加密 (AES128_ECB_enc()) 和解密 (AES128_ECB_dec ()) 所需的基本设计模式。(代码来源:Maxim Integrated)

身份验证协议

要为应用中使用的高级协议提供安全基础,具有强鲁棒性的加密算法实现尤其重要。像传输层安全 (TLS) 这样的较高层级协议通常使用一组定义的加密算法(称为密码套件)来执行运算。在 TLS 中,从约定的密码套件提取的算法有助于确保物联网设备客户端与主机服务器之间的通信会话实现身份验证和机密性。TLS 1.2[8] 会通过一个特定事务处理序列,在进行数据交换之前,协商参数、执行身份验证和交换会话密钥(图 3)。

TLS 1.2 会话创建协议示意图图 3:TLS 1.2 会话创建协议使用约定密码套件提供的各种算法进行身份验证、密钥交换和持续的数据交换。(图片来源:Texas Instruments)

鉴于安全证书中包含每个参与者各自的公钥,可通过验证安全证书,确定服务器以及客户端(可选)的身份以确保实现身份验证。在此期间,每个参与者都会发送一条使用其私钥加密的消息。由于接收到的公钥仅能解密用其关联私钥加密的消息,因此每个参与者都可以确认证书提供者实际拥有该证书。

在下一个 TLS 阶段,参与者执行一系列事务处理,以创建共享会话密钥。该共享会话密钥随后会用来加密实际的消息流量,从而确保该会话消息交换的机密性。

多种协议选择使开发人员可以优化此通用 TLS 会话的创建过程,但有时会影响整体安全性。此外,在参数交换过程中,开发人员可以使用不同的密码套件,为各个协议阶段选择合适的 TLS 1.2 支持算法组合,具体包括:

  • 密钥构建:RSA、DH、ECDH
  • 身份验证:RSA、DSA、ECDSA
  • 加密法:3DES、AES
  • 消息验证:SHA

最新版本的 TLS 为 TLS 1.3[9],该协议规定先执行密钥交换以更好地保护会话创建过程,从而增加了额外的安全性。更重要的是,TLS 1.3 在很大程度上弃用了 TLS 1.2 的密码套件,转而使用更强大的算法,包括基于 HMAC 的提取和扩展密钥派生函数 (HKDF),以及带有关联数据的认证加密 (AEAD) 算法。AEAD 算法满足了确保消息真实性、完整性和机密性的广泛需求。这些算法通过将加密消息与 MAC 绑定实现上述要求,而加密与 MAC 可按照串行方式(图 4,左)、并行方式(图 4,右)或两者并用方式生成。

AEAD 提供身份验证和机密性示意图图 4:AEAD 使用先加密后生成 MAC(左)与同时加密和生成 MAC(右)方式,分别进行串行或并行 MAC 计算,然后将 MAC 与密文绑定从而提供身份验证与机密性。(图片来源:维基百科)

增加安全强度

加密算法与相关协议的发展过程,可以说是决心强化安全性的加密专家与同样坚定的破解者之间不断追逐的竞赛。例如,为了加强安全性,专家开发了 ECDSA 作为 DSA 的 ECC 变体,而 DSA 本身则是更早期加密法的变体。因此,ECDSA 的安全强度与 DSA 相同,但密钥大小则大幅缩小。

在密码学中,算法的安全强度取决于密钥位数 x 和攻击将需要约 2x 次运算才能推演出算法所隐藏私钥的预期。根据这些条件,不同类别的算法可能需要截然不同的密钥长度,才能达到相当安全级别(表 1)。

不同类别的加密算法表表 1:不同类别的加密算法可能需要截然不同的公钥 (L) 或私钥(N、k、f)大小,才能实现级别相当的安全强度。(图片来源:NIST)

在这张来自 NIST 的表格中,FFC 算法参数 LN 分别对应于公钥和私钥的大小。kf 分别对应于 IFC 和 ECC 算法的密钥大小。NIST 指出,安全强度 ≤80 的算法(表中橘色背景的单元格)不准再用于保护政府信息,而其他算法(黄色背景的单元格)基于效率考虑,尚未纳入 NIST 标准。

在追求更高安全强度的趋势下,加密法和建议的密码套件也因此而不断发展。例如,美国国家安全局 (NSA) 商业国家安全算法 (CNSA) 套件取代了早期的 NSA Suite B,并建议使用更稳健的参数来保护被列为最高机密的信息(表 2)。

加密算法表以及最低安全强度建议表 2:NSA 建议的 CNSA 套件包含加密算法以及保护高度敏感信息所需的最低安全强度建议。(图片来源:Digi-Key,数据来源于 NSA)

展望未来,量子计算功能的出现会为整个安全领域,特别是加密算法,带来巨大的断层。

结语

物联网设备和其他互连设计面临着越来越多的威胁,因此需要更强大的基于多种加密算法的安全方法。这些算法依赖于一系列转换与数学运算,将明文加密为密文,再将密文解密为明文,目的是让破坏安全性的行为徒劳无功。如上所述,可以采用基于硬件的方式实现这些算法,因而开发人员能够更轻松地在设计中整合强大的安全功能,而不会影响功能和性能方面的主要要求。

参考文献:

  1. How a fish tank helped hack a casino
  2. FIPS PUB 197:官方 AES 标准
  3. IETF RFC 3526 (DH)
  4. NIST SP 800-56B Rev. 1 (DOI) (RSA)
  5. NIST SP 800-56A (ECDH)
  6. FIPS Pub 186-4(数字签名)
  7. FIPS PUB 180-4:安全哈希标准 (SHS)
  8. IETF RFC 5246 (TLS 1.2)
  9. IETF RFC 8446 (TLS 1.3)

免责声明:各个作者和/或论坛参与者在本网站发表的观点、看法和意见不代表 DigiKey 的观点、看法和意见,也不代表 DigiKey 官方政策。

关于此作者

Stephen Evanczuk

Stephen Evanczuk 拥有 20 多年的电子行业编辑经验,主题涉猎广泛,涵盖硬件、软件、系统以及包括物联网在内的各种应用。他拥有神经网络领域的神经科学博士学位,曾经从事航空航天领域大规模分布式安全系统和算法加速方法方面的工作。目前,他不是在撰写技术和工程文章,就是在研究深度学习在识别和推荐系统方面的应用。

关于此出版商

DigiKey 北美编辑