编码算法
- ASCII编码 2字节编码
- UNICODE编码,需要3个字节的编码
- UTF-8由UNICODE转换过来,为了节约空间,不定长编码
- URL编码
- URL编码是浏览器发送数据给服务器时使用的编码,它通常附加在URL的参数部分。
https://www.baidu.com/s?wd=%E4%B8%AD%E6%96%87 - 编码规则(很多服务器只识别ASCII)
- 如果字符是A
Z,az,0~9以及-、_、.、*,则保持不变; - 如果是其他字符,先转换为UTF-8编码,然后对每个字节以%XX表示。
- 如果字符是A
- URL编码是浏览器发送数据给服务器时使用的编码,它通常附加在URL的参数部分。
- Base64编码
- 把任意长度的二进制数据变为纯文本,编码后数据量会增加1/3
哈希算法
哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
- 相同的输入一定得到相同的输出;
- 不同的输入大概率得到不同的输出。
- 作用:验证原始数据是否被篡改(下载软件,存储用户口令)
- 好的哈希算法碰撞概率低,无法猜测输出
- 常见 MD5, SHA-1, SHA-256, SHA-512
数据库不存储用户口令明文,经过SHA加密。用户输入口令后,经过SHA与存储的SHA对比。尽量不要输入过于简单的密码,或者给用户口令加盐后哈希,
digest = hash(salt + input)避免彩虹表反查。
Hmac算法
salt可以看作是一个额外的“认证码”,同样的输入,不同的认证码,会产生不同的输出。因此,要验证输出的哈希,必须同时提供“认证码”
Hmac算法总是和某种哈希算法配合起来用的。例如,我们使用MD5算法,对应的就是HmacMD5算法,它相当于“加盐”的MD5java HmacMD5 ≈ md5(secure_random_key, input)
HmacMD5随机生成key长度是64字节,更安全;
key混入哈希的算法。验证此哈希时,除了原始的输入数据,还要提供key。
对称加密算法
对称加密算法用一个密码进行加密和解密,又叫私钥加密算法。java secret = encrypt(key, message);
而解密则相反,它接收密码和密文,然后输出明文。:java plain = decrypt(key, secret);
key的长度是固定的。常见生成key并加密算法AES长度有128/192/256
加密 123 =》AES( 123 + key ) =》@#$
解密 @#$ =》AES( key + @#$ ) =》123
口令加密算法
WinZIP和WinRAR对压缩包的加密和解密,就是使用对称加密算法但是我们解压时发现输入的密码不是固定的,源文件相当于密文,我们输入的密码相当于key,
根据上一节对称算法 解密 @#$ =》AES(key + @#$) =》123 但是我们此时发现输入的key长度并不是固定的。
实际上key是通过用户密码加一个安全随机的口令生成的,也就是PBE算法Password Based Encryption;
key=PBE(用户输入+随机口令)
加密过程就变为 原始数据 123(例如被压缩文件) =》AES( 123 + PBE(用户输入+随机口令) ) =》@#$
解密过程就变为 密文 @#$(例如待解压文件) =》AES( PBE(用户输入+随机口令) + @#$ ) =》123
但是我们发现解密时我们只输入了用户密码,这里可以理解为压缩文件本身自带随机口令,银行u盾
用户输入密码+U盾(随机口令)==key。
密钥交换算法
在不安全的信道上传递加密文件是没有问题的,因为黑客拿到加密文件没有用。但是,传递密钥成为了问题,对方只有拿到了密钥,才能解开加密文件
DH(Diffie-Hellman)算法解决了密钥在双方不直接传递密钥的情况下完成密钥交换,这个神奇的交换原理完全由数学理论支持。
- 甲首选选择一个素数p,例如97,底数g是p的一个原根,例如5,随机数a,例如123,然后计算A=g^a mod p,结果是34,然后,甲发送p=97,g=5,A=34给乙;
- 乙方收到后,也选择一个随机数b,例如,456,然后计算B = g^b mod p,结果是75,乙再同时计算s = A^b mod p,结果是22;
- 乙把计算的B=75发给甲,甲计算s = B^a mod p,计算结果与乙算出的结果一样,都是22。
所以最终双方协商出的密钥s是22。注意到这个密钥s并没有在网络上传输。而通过网络传输的p,g,A和B是无法推算出s的,由于实际算法选择的素数是非常大,且通过模除计算,会有非常多种可能。
a看成甲的私钥,A看成甲的公钥,b看成乙的私钥,B看成乙的公钥,DH算法的本质就是双方各自生成自己的私钥和公钥,私钥仅对自己可见,然后交换公钥,并根据自己的私钥和对方的公钥,生成最终的密钥secretKey,DH算法通过数学定律保证了双方各自计算出的secretKey是相同的。
DH算法并未解决中间人攻击,消除中间人攻击需要其他方法。
假设甲乙在交换公钥时被丙截获,丙把自己的公钥分别发送给甲乙两人,就变成了,甲丙通信,丙乙通信。甲发消息的话相当于甲生成A, p, g给丙,丙直接充当乙,自己生成一套b,B,若收到乙的直接丢弃。同样乙发消息。
非对称加密算法
- 公钥-私钥对解密
非对称加密的典型算法就是RSA算法
非对称加密就是加密和解密使用的不是相同的密钥:只有同一个公钥-私钥对才能正常加解密。
对称加密需要协商密钥,而非对称加密可以安全地公开各自的公钥,在N个人之间通信的时候:使用非对称加密只需要N个密钥对,每个人只管理自己的密钥对。而使用对称加密需要则需要N*(N-1)/2个密钥,因此每个人需要管理N-1个密钥,密钥管理难度大,而且非常容易泄漏。非对称加密的缺点是运算速度非常慢,比对称加密要慢很多。
非对称加密总是和对称加密一起使用。假设小明需要给小红需要传输加密文件,他俩首先交换了各自的公钥,然后:
- 小明生成一个随机的AES口令,然后用小红的公钥通过RSA加密这个口令,并发给小红;
- 小红用自己的RSA私钥解密得到AES口令;
- 双方使用这个共享的AES口令,用AES加密通信。
非对称加密在第一步,加密“AES口令”。这也是我们在浏览器中常用的HTTPS协议的做法,即浏览器和服务器先通过RSA交换AES口令,接下来双方通信实际上采用的是速度较快的AES对称加密,而不是缓慢的RSA非对称加密。
既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
数字签名
私钥加密得到的密文实际上就是数字签名,要验证这个签名是否正确,只能用私钥持有者的公钥进行解密验证。使用数字签名的目的是为了确认某个信息确实是由某个发送方发送的,任何人都不可能伪造消息,并且,发送方也不能抵赖。
- 签名针对原始消息的哈希进行签名(私钥并没有泄漏)
- 用户总是使用自己的私钥进行签名,所以,私钥就相当于用户身份。而公钥用来给外部验证用户身份。
常用数字签名算法有:
MD5withRSA
SHA1withRSA
SHA256withRSA
数字证书
- 摘要算法用来确保数据没有被篡改,非对称加密算法可以对数据进行加解密,签名算法可以确保数据完整性和抗否认性,把这些算法集合到一起,并搞一套完善的标准,这就是数字证书。
- 数字证书就是集合了多种密码学算法,用于实现数据加解密、身份认证、签名等多种功能的一种安全标准。
- 数字证书可以防止中间人攻击,因为它采用链式签名认证,即通过根证书(Root CA)去签名下一级证书,这样层层签名,直到最终的用户证书。
