写给开发人员的实用密码学(一)—— 概览

本文主要翻译自 Practical-Cryptography-for-Developers-Book

你是软件开发人员吗?有时你会需要在日常工作中使用哈希、加密或数字签名等密码学工具吗?你认为密码学很复杂,充满了数学知识,而且只适合书呆子吗?不,不是这样滴,每个开发人员都可以学习如何使用加密算法。

从开发人员的角度理解密码学概念不需要你是一个厉害的数学家。这个系列的文章将尽量以最浅显的方式教你应用密码学的基础知识,而且包含大量循序渐进的代码示例和实践练习——就像你学习 Web 开发、数据库或 APP 开发一样。

没错,如果你能够学会 Web 开发或 RESTful 服务,那么你也完全可以学会实用密码学。这就像学习一个新的 API 或一个新的 Web 开发框架,只要掌握了概念 + 加密库 API + 工具 + 最佳实践,你就学会了实用密码学~

在这个系列中,你将学习如何使用密码算法和密码系统,如哈希、MAC 码和密钥派生函数 (KDF)、随机生成器、密钥交换协议、对称密码算法、加密方案、非对称密码系统、公钥密码学、椭圆曲线、数字签名和量子安全加密算法,以及现代加密工具和库。

密码学已经从第一代广泛应用的密码学算法(比如已经退役的 MD5 跟 DES),发展到现代密码学算法 (如 SHA-3, Argon2 以及 ChaCha20)。

让我们首先跟一些基本的密码学概念混个脸熟:

  • 哈希函数,如 SHA-256, SHA3, RIPEMD 等
  • 散列消息认证码 HMAC
  • 密钥派生函数 KDF,如 Scrypt
  • 密钥交换算法,如 Diffie-Hellman 密钥交换协议
  • 对称密钥加密方案,如 AES-256-CTR-HMAC-SHA-256
  • 使用公私钥的非对称密钥加密方案,如 RSA 和 ECC, secp256k1 曲线跟 Ed25519 密码系统
  • 数字签名算法,如 ECDSA
  • (entropy)与安全随机数生成
  • 量子安全密码学

上述这些概念涉及到技术被广泛应用在 IT 领域,如果你有过一些开发经验,可能会很熟悉其中部分名词。如果不熟也没任何关系,本书的目的就是帮你搞清楚这些概念。

这个系列的文章会按上面给出的顺序,依次介绍这些密码学概念以及如何在日常开发中使用它们。

不过在开始学习之前,我们先来了解一下什么是密码学,以及密码学的几大用途。

密码学(Cryptography)是提供信息安全保护的科学。它在我们的数字世界中无处不在,当你打开网站时、发送电子邮件时、连接到 WiFi 网络时,使用账号密码登录 APP 时、使用二步认证验证码认证身份时,都有涉及到密码学相关技术。因此开发人员应该对密码学有基本的了解, 以避免写出不安全的代码。至少也得知道如何使用密码算法和密码库,了解哈希、对称密码算法、非对称密码算法(cipher)与加密方案这些概念,知晓数字签名及其背后的密码系统和算法。

密码学的一大用途,就是进行数据的安全存储和安全传输。这可能涉及使用对称或非对称加密方案加密解密数据,其中一个或多个密钥用于将数据从明文转换为加密形式或者相反。

对称加密(如 AES、Twofish 和 ChaCha20)使用相同的密钥(一个密钥)来加密和解密消息,而非对称加密使用公钥密码系统(如 RSA 或 ECC)和密钥对(两个密钥)来进行这两项操作。

单纯使用加密算法是不够的,这是因为有的加密算法只能按块进行加密,而且很多加密算法并不能保证密文的真实性、完整性。因此现实中我们通常会使用加密方案进行数据的加密解密。加密方案是结合了加密算法、消息认证或数字签名算法、块密码模式等多种算法,能同时保证数据的安全性、真实性、完整性的一套加密方案,如 AES-256-CTR-HMAC-SHA-256、ChaCha20-Poly1305 或 ECIES-secp256k1-AES-128-GCM。后面我们会学到,加密方案的名称就是使用到的各种密码算法名称的组合。

密码学提供了保证消息真实性(authenticity)、完整性(integrity)和不可否认性 (non-repudiation)的方法:数字签名算法与消息认证(MAC)算法。

大多数数字签名算法(如 DSA、ECDSA 和 EdDSA)使用非对称密钥对(私钥和公钥)干这个活:消息由私钥签名,签名由相应的公钥验证。在银行系统中,数字签名用于签署和批准付款。在区块链签名交易中,用户可以将区块链资产从一个地址转移到另一个地址,确保转移操作的真实、完整、不可否认。

消息认证算法(如 HMAC)和消息认证码(MAC 码)也是密码学的一部分。MAC 跟数字签名的功能实际上是一致的,区别在于 MAC 使用哈希算法或者对称加密系统。

密码学的另一个部分,是(entropy,指不可预测的随机性)和随机数的安全生成(例如使用 CSPRNG)。

安全随机数理论上是不可预测的,开发人员需要关心的是你使用的随机数生成器是否足够安全。很多编程语言中被广泛使用的随机数生成器都是不安全的(比如 Python 的 random 库),如果你在对安全有严格要求的场景下使用了这种不安全的随机生成器,可能会黑客被预测到它生成的随机数,导致系统或者 APP 被黑客入侵。

密码学定义了密钥交换算法(如 Diffie-Hellman 密钥交换和 ECDH)和密钥构建方案,用于在需要安全传输消息的两方之间安全地构建加密密钥。这种算法通常在两方之间建立新的安全连接时执行, 例如当你打开一个现代 HTTPS 网站或连接到 WiFi 网络时。

密码学提供了加密哈希函数(如 SHA-3 和 BLAKE2)将消息转换为消息摘要/数字指纹(固定长度的散列),确保无法逆向出原始消息,并且几乎不可能找到具有相同哈希值的两条不同消息。

例如,在区块链系统中,哈希用于生成区块链地址、交易 ID 以及许多其他算法和协议。在 Git 中, 加密哈希用于为文件和提交生成唯一 ID。

而密钥派生函数(如 Scrypt 和 Argon2)通过从基于文本的 Password 安全地派生出哈希值(或密钥),并且这种算法还通过注入随机参数(盐)和使用大量迭代和计算资源使密码破解速度变慢。

密码学提供密钥的生成手段。因为人类只擅长记忆字符形式的密码,但是各种加密算法需要的密钥都是一个非常大的、保密的数字,所以密码学需要提供手段将字符串转换成密钥。

在密码学当中,香农提出的混淆(confusion)与扩散(diffusion)是设计安全密码学算法的两个原则。

混淆使密文和对称加密中密钥的映射关系变得尽可能的复杂,使之难以分析。如果使用了混淆,那么输出密文中的每个比特位都应该依赖于密钥和输入数据的多个部分,确保两者无法建立直接映射。 混淆常用的方法是「替换」与「排列」。

扩散」将明文的统计结构扩散到大量密文中,隐藏明文与密文之间的统计学关系。使单个明文或密钥位的影响尽可能扩大到更多的密文中去,确保改变输入中的任意一位都应该导致输出中大约一半的位发生变化,反过来改变输出密文的任一位,明文中大约一半的位也必须发生变化。 扩散常用的方法是「置换」。

这两个原则被包含在大多数散列函数、MAC 算法、随机数生成器、对称和非对称密码算法中。

说了这么多,作为一个程序员,我学习密码学的目的,是为了搞懂如何在编程语言中使用现代密码库, 并从中挑选合适的算法、使用合适的 API 参数。

程序员经常会自嘲日常复制粘贴,但是在编写涉及到密码学的代码时,一定要谨慎处理!盲目地从 Internet 复制/粘贴代码或遵循博客中的示例可能会导致安全问题;曾经安全的代码、算法或者最佳实践,随着时间的推移也可能变得不再安全。

本系列文章的后续部分,会分别介绍上述密码学概念,并使用 Python 演示其用法,其他语言的写法网上也很容易找到。

相关内容