浏览器 F12 控制台(Console),触手可及的人机交互,JavaScript 命令行,轻量级,随时轻松编程实践。
1. 关于加密
上学时递小纸条,尤其是需要中间人传递时,是不是使用过一套约定的符号代替普通的文字?特别有必要!
图
广义来讲,保护信息的各种方式都属于加密范畴,而保护的形式、角度、等级和目标是多种多样的。
2. 几种情形下的策略
(1)内容是否被修改
电视剧里,经常有材料被情敌偷偷修改然后蒙冤的场景。何解?
策略:让内容中每一个字节都参与一项运算得出一个结果记录下来,如果计算结果变了,说明内容被修改过。
这里运算得出的结果叫做摘要,这个算法叫消息摘要算法,也叫单向散列函数。算法的科学性很重要,常见的算法有:MD5、SHA1、SHA256、SHA512、HmacMD5、HmacSHA1、HmacSHA256 等。
(2)不要给别人看到
这个,只能说难免会被别人看到。
策略:使用密钥变换内容,让别人看到也不知道为何物,通过密钥才可还原内容。
这种通过相同的密钥来加密和解密的算法,叫对称加密算法。常见算法DES、3DES(TripleDES)和AES(Advanced Encryption Standard)等。AES 根据密钥长度不同又分为AES-128 AES-192 AES-256 对应16 24 32 字节。
这些算法,通常是按块来进行加密的,如 16 个字节为一块。当最后一块不够 16 个字节时,通常是采用补齐的策略,补齐的方式也有不同讲究。
策略一,数据长度不对齐时使用0填充,否则不填充,但补的0解密后无法区分是补的还是原本就有的,只适合以\0结尾的字符串加密,此谓之 ZeroPadding。
策略二,补充的字节值设定为补充的数量,如要补充5个字节,则这5个字节的值都为 5,这样根据最后一个字节可得到填充数据的长度,在解密后可以准确删除填充的数据。但如果刚好整块无需补充,为了仍然满足最后一个字节表示填充的数据长度,填充一整块,值为块长度。此种方式有 PKCS7Padding,它假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小。PKCS5Padding,PKCS7Padding的子集,块大小固定为8字节。
分块加密时,每块采用完成相同的加密过程,则可以并行加密再拼接,但当内容中有多块相同的内容时加密结果会一样,而这种重复会为破解提供线索,于是多种加密模式被提出。以下是两种最常见的模式。
Electronic Code Book(ECB)
电子密码本模式
最基本的加密模式,也就是通常理解的加密,相同的明文将永远加密成相同的密文,无初始向量,容易受到密码本重放攻击,一般情况下很少用。
Cipher Block Chaining(CBC)
密码分组链接模式
明文被加密前要与前面的密文进行异或运算后再加密,因此只要选择不同的初始向量,相同的密文加密后会形成不同的密文,这是目前应用最广泛的模式。CBC加密后的密文是上下文相关的,但明文的错误不会传递到后续分组,但如果一个分组丢失,后面的分组将全部作废(同步错误)。
(3)是否真的来自对的人
对称加密中,接收方需要知道密钥,这个密钥本身的保密就成为了问题。密钥泄漏,意味着正确解密的消息也变得不可靠,也许是伪造的。
策略:公开密钥,即发给我的消息,使用公开密钥加密,我收到之后只可用我的私有密钥解密。
此谓之非对称加密算法,一种强大的密钥保密方法。这离不开理论上的研究成果。
W.Diffie和M.Hellman 1976年在IEEE Trans.on Information刊物上发表了“ New Direction in Cryptography”文章,提出了“非对称密码体制即公开密钥密码体制”的概念,开创了密码学研究的新方向
非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。
为了验证是不是对的人,可以要求发送放对内容提取摘要,并使用其私钥加密,将结果附在后边作为签名一并发送。这样,就可以使用发送放的公钥来解密这个签名并验证其一致性,如果一致说明是对的人发过来的。此过程谓之签名验签。
使用最广泛的是RSA算法。
3. 常见算法实操
很多常见的加密算法在 CryptoJS 中有实现,首先,在控制台引入扩展脚本。
var s = document.createElement("script");
s.src = "https://cdn.bootcss.com/crypto-js/3.1.9-1/crypto-js.min.js";
document.body.appendChild(s);
MD5
CryptoJS.MD5("hello").toString();
// 得到 5d41402abc4b2a76b9719d911017c592
CryptoJS.MD5("he11o").toString();
// 得到 8f3946d5aaad6af7ebd41b6a6e6b1756
AES128
var message = "我想对你说...";
var key = "%$123456";
var cipher = CryptoJS.AES.encrypt(message, key);
console.log(cipher.toString());
加密结果 U2FsdGVkX1/Ry7m4YU7aTXizLMAGhn2EwZf555rz8neh6FP6/4p9CUaZpnBxvOKT
解密过程
var cipher = "U2FsdGVkX1/Ry7m4YU7aTXizLMAGhn2EwZf555rz8neh6FP6/4p9CUaZpnBxvOKT";
var key = "%$123456";
var plain = CryptoJS.AES.decrypt(cipher, key);
var oritext = CryptoJS.enc.Utf8.stringify(plain);
console.log(oritext);
加密的内容为16进制数据时,可以利用以下方式将16进制字符串转换成字节数组。
var key = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");
var mess = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
var r = CryptoJS.AES.encrypt(mess, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding })
r.ciphertext.toString();
计算结果 c6a13b37878f5b826f4f8162a1c8d879
RSA
CryptoJS 当前尚未支持 RSA,可以引入以下 JS 扩展。
var s = document.createElement("script");
s.src = "https://cdn.bootcdn.net/ajax/libs/jsencrypt/3.2.0/jsencrypt.min.js";
document.body.appendChild(s);
使用公钥加密
var e = new JSEncrypt();
e.setPublicKey("......");
var cipher = e.encrypt("hello world!");
console.log(cipher);
OVNmfqDMAxHoiMbNHNQ4Olrb0BHGLHEPXM0EAJ/hTwEJsz+igrLIPnrqf1ABmWnoj6cOOcGNroYLa2xZ9/TkaF5UKG+H+RrjpbHHQVe3mWWlDsX9bZ/m8lP3izntwKHdklH+2vfeOlSJ3+PK3O6ILWvaVM4PVCzVo9lPiN7NkIE=
使用私钥解密
var d = new JSEncrypt();
d.setPrivateKey("......");
var plain = d.decrypt(cipher);
console.log(plain);
反过来使用私钥加密公钥解密也是可以的,只是一般的工具方法,只会提供私密生成签名,公钥验证签名,但这足够了。
更详细用法,请参考 https://github.com/travist/jsencrypt/
4. 加密和破解
直接来看看二战期间的故事,以下内容引用自 https://zhidao.baidu.com/question/13366735.html
二次大战中,英国倾全国之力,破译了德国的“谜语机”密码,为战胜纳粹德国作出重要贡献;美国则破译了日军密码,由此发动空袭,击毁日本大将山本五十六的座机。丘吉尔说,密码员就是“下了金蛋却从不叫唤的鹅”。
用纳瓦霍语编制军事密码,是一个叫菲利普·约翰逊的白人出的主意。约翰逊的父亲是传教士,曾到过纳瓦霍部落,能说一口流利的纳瓦霍语,而在当时,纳瓦霍语对部落外的人来说,无异于“鸟语”。极具军事头脑的约翰逊认为,如果用纳瓦霍语编制军事密码,将非常可靠而且无法破译。因为这种语言口口相传,没有文字,其语法、声调、音节都非常复杂,没有经过专门的长期训练,根本不可能弄懂它的意思。另外,根据当时的资料记载,通晓这一语言的非纳瓦霍族人全球不过30人,其中没有一个是日本人。
1942年初,约翰逊向美国太平洋舰队上将克莱登·沃格尔提出了这个建议。约翰逊说,根据他的实验,用纳瓦霍语编制的密码可以在20秒内将三行英文信息传递出去,而同样的信息用机器密码却需要30分钟。
沃格尔接受了约翰逊的建议。1942年5月,第一批29名纳瓦霍人被征召入伍,并被安排在加利福尼亚一处海滨编制密码。他们根据纳瓦霍语共创建了有500个常用军事术语的词汇表。由于纳瓦霍语没有描述现代军事设备的词语,因此他们经常使用比喻说法和拟声词。
在太平洋战争期间,美国海军陆战队共征召了420名纳瓦霍族人充当密码通讯员。这些纳瓦霍族人参加了美军在太平洋地区发动的每一场战役。他们用密码下达战斗命令,通报战情,紧急时还参加战斗。他们的英勇献身,为最终打败日本军国主义者起到重要作用。
攻占硫磺岛是美军在太平洋战争中打的一场经典战役,美军把旗帜插上硫磺岛的照片,成为美国在二战中浴血奋战的象征。硫磺岛战役结束后,负责联络的霍华德·康纳上校曾感慨地说:“如果不是因为纳瓦霍人,美国海军将永远攻占不了硫磺岛。”当时,康纳手下共有6名纳瓦霍密码员,在战斗开始的前两天,他们通宵工作,没有一刻休息。整个战斗中,他们共接发了800多条消息,没有出现任何差错。