作者 | 梁唐
出品 | 公众号:Coder梁(ID:Coder_LT)
大家好,日拱一卒,我是梁唐。
今天我们继续麻省理工missing smester,消失的学期的学习。这一节课的内容关于信息安全和密码学。
B站视频链接:https://www.bilibili.com/video/BV1x7411H7wa?p=9
密码学和信息安全在如今的互联网行业当中非常重要,相关的理论知识和算法也在计算机系统的方方面面都被用到。虽然我们不一定会从事安全相关的工作,但对密码学以及信息安全的基本知识和概念有所了解还是很有必要的。
日拱一卒,欢迎大家打卡一起学习。
这节课上我们会关注安全和密码学相关的概念,这些概念和之前介绍的一些工具也有关联。比如git当中用到的hash函数或者是SSH当中密钥生成函数或者是对称/非对称密码体系。
本节课不能作为计算机系统安全以及密码学的替代。没有从事训练,不要轻易从事安全相关的工作,也不要修改或创造加密相关算法。
这节课是对基础密码学概念的一个非正式的介绍。这节课上我们不会教你如何设计安全系统或者是加密协议,但我们希望能够让你对频繁使用的程序以及协议有一个总体上的了解。
熵用来衡量混乱程度,这是一个非常有用的概念,在很多领域当中都有广泛应用。比如当我们决定密码强度的时候。
上图是关于密码强度的漫画,漫画当中说"correcthorsebatterystaple"比"Tr0ub4dor&3"这样的密码更加安全,但是它是怎么定义安全程度的呢?
在计算机领域当中,熵的计算单位是bit,当均匀地从一系列值当中随机选择时,它的熵等于log_2(可能性总数)。抛一枚均匀的硬币的熵是1 bit,一个六面骰子的熵大约是2.58 bit。
你可以认为黑客们知道密码的模型(最短长度、最长长度、包含的字符种类等),但不知道密码是如何被随机选择的(比如通过骰子)。
多少bit的熵才足够呢?这取决于你的威胁模型。对于在线穷举的猜测,漫画告诉我们大约40bit的熵就足够了。而对于离线的枚举,一般需要更强的密码(比如80bit或更多)。
密码hash函数可以将任意大小的数据映射成一个固定大小的输出,并且还有一些特殊的属性。一个hash函数的定义大体如下:
hash(value: array<byte>) -> vector<byte, N> (N对于该函数固定)
SHA1是一个很好的例子,它被用在Git当中。它可以将任意长度的输入转化成160bit的输出(可以被表示成长度40的十六进制数)。我们可以使用sha1sum
命令来使用SHA1函数:
$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'Hello' | sha1sum
f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0
从更高维度来说,hash函数拥有不可逆性并且结果看上去非常随机。想要从hash之后的结果倒推出输入非常困难,几乎不可能完成。一个hash函数拥有如下特性:
hash(m) = h
,很难通过h倒推得到mm_1
很难找到另外一个输入m_2
使得它们hash之后的结果一样m_1, m_2
使得hash(m_1) = hash(m_2)
(这比上一条要求更高)注意:虽然SHA-1对于某些用途还在使用,但它已经不再被认为是一个很强的密码hash函数了。你可以参考密码hash函数的生命周期这篇文章(https://valerieaurora.org/hash.html)。另外,推荐特定的hash函数并非是本节课的重点,如果你想要使用它,最好先系统学习密码学和信息安全。
密钥生成函数(key derivation functions KDFs)是一个和密码hash函数近似的概念,它用在许多场景,比如生成固定长度的输出结果,用作一些密码学算法当中充当密钥。通常KDF生成函数比较缓慢,这是为了抵抗暴力破解攻击。
运行缓慢可以让暴力穷举枚举的破解方法消耗更多的时间。
关于密码学,你可能首先想到的就是隐藏消息内容。对称加密通过以下几个方法来完成这个功能:
keygen() -> key (this function is randomized)
encrypt(plaintext: array<byte>, key) -> array<byte> (the ciphertext)
decrypt(ciphertext: array<byte>, key) -> array<byte> (the plaintext)
加密算法encrypt生成密文(ciphertext),在没有key的情况下,我们很难将密文破译。
解密函数要确保正确解密需要保证:decypt(entrypt(m, k), k) = m
AES是现在常用的一种对称加密算法。
key = KDF(passphrase)
,接着存储encrpy(file, key)
非对称的意思是会使用两个功能不同的密钥。一个是私钥,不对外公开。一个是公钥,可以被公开分享,并且不会影响安全性(不像对称加密不能分享密钥)。
非对称加密提供以下几个函数来实现加密/解密和签名/验证(sign/verify):
keygen() -> (public key, private key) (this function is randomized)
encrypt(plaintext: array<byte>, public key) -> array<byte> (the ciphertext)
decrypt(ciphertext: array<byte>, private key) -> array<byte> (the plaintext)
sign(message: array<byte>, private key) -> array<byte> (the signature)
verify(message: array<byte>, signature: array<byte>, public key) -> bool (whether or not the signature is valid)
加密/解密函数和对称加密当中类似。密文可以使用公钥进行加密,得到密文(ciphertext),在没有私钥的情况下,很难得到原文(plaintext)。
解密函数保证decrypt(encrypt(m, public_key), private_key) = m
对称加密和非对称加密可以类比于机械锁,对称加密系统就像是门锁:只要有钥匙就可以进行开锁和上锁。非对称加密就像是一个可以取下的挂锁,你可以把一个打开的挂锁给别人(公钥)上锁,并保留钥匙(私钥)。其他人可以上锁,但只有私钥才能开锁。
签名/验证函数和书面签名有相似的属性——很难被伪造。不论消息是什么,在没有私钥的情况下,很难生产可以使得verify(message, signature, public_key)
返回True的签名。当然,在私钥和公钥对应时,verify会返回True,即verify(message, signature, public_key)=true
非对称加密非常好用,但是也有一个巨大的挑战,就是如何将公钥分发/对应现实世界的实体。关于这个问题有很多解决方案。信号(signal)使用一种简单的方法:在第一次使用的时候信任它,同时支持用户面对面、线下交换公钥。
PGP的策略不同,它使用信任网络。keybase主要通过另外一种叫做社交证明(social proof)和一些其他的设计。
每个模型都有它的特点,我们更倾向于keybase的模式。
每个人都有必要使用密码管理器比如keepassxc,pass,1password等。密码管理器可以让我们不同的网站使用不同的、随机且高熵的密码,并且会将所有的密码使用对称加密的方式来存储起来。
使用密码管理器可以让你不需要重复使用密码,并且可以使用高熵密码,最重要的是你只需要记住一个密码就可以尽可能避免密码泄漏、被撞库等隐患。
两步验证(2FA)要求用户使用密码以及另外一个身份验证器来消除密码泄漏以及钓鱼攻击的风险。
对笔记本电脑的硬盘进行全盘加密是防止因设备丢失而信息泄露的简单且有效方法。Linux的cryptsetup + LUKS, Windows的BitLocker,或者macOS的FileVault都使用一个由密码保护的对称密钥来加密盘上的所有信息。
使用singal或keybase可以保证端到端的通信安全。
但这需要使用联系人的公钥,要确保安全的话,需要在线下方式验证singal或者keybase的公钥。
我们在之前的一堂课讨论了SSH和SSH密钥的使用。让我们从密码学的角度来分析一下它们。
当你运行ssh-keygen时,它会生成一个非对称加密的密钥对,public_key和private_key。这是随机生成的,通常会使用操作系统提供的熵(从硬件事件上获取)。公钥可以被分发出去,私钥需要加密保存在磁盘上。
ssh-keygen程序会提示用户输入一个密码,并将它输入密钥生成函数来生成密钥。这会被对称加密算法进行加密。
在使用的时候,当服务器知道了客户端的公钥之后(存储在.ssh/authorized_keys
文件中),尝试链接的客户端可以使用非对称加密签名来验证客户的身份。
简单来说,服务器选择一个随机数发送给客户。客户使用私钥进行签名之后再发送给服务器,服务器随后使用存储的公钥来验证签名。这种方式可以很方便地验证客户是否持有对应的私钥,如果验证通过的话,那么允许客户登录访问。
喜欢本文的话不要忘记三连~