说完Go里面的md5的用法,这篇文章咱说说用的比较多的加密方式在Go里面如何实现。首先,科普一下,一般待加密的内容被叫作明文,加密使用的关键元素被称为秘钥,加密的结果被称为密文,当然其中还有一个非常关键的加密算法。
一般加密算法可分为对称加密和非对称加密这两个分类,这两者区别很明显,对称加密是指我们拿到秘钥和密文可以解密出明文,在加密和解密时使用的是同一个秘钥;而非对称加密算法需要两个密钥来进行加密和解密,这两个密钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。
本篇文章不是讲如何在Go里面实现这些加密算法,仔细看一下Go标准库里面crypto库,你会发现其实Go已经实现很多了加密算法,但是很多人不知道咋用,正如MD5算法一样,它没有提供一个非常简单易用的对外接口,需要你自己再封装一遍,这一点非常不好。。。
今天我们主要说两种最常用的加密算法:AES对称加密、RSA非对称加密。
AES对称加密
AES(Advanced Encryption Standard)是最常见的对称加密算法,但是这个算法分很多模式,不同模式的实现方式又有很大差异,比如ECB、CBC、OFB、CFB,详细技术细节这里就不多说了。
有几点需要注意,AES对加密key的长度要求必须固定为16、24、32位,也就是128、192、256比特,所以又有一个AES-128、AES-192、AES-256这种叫法,位数越大安全性越高但加密速度越慢。最关键是对明文长度也有要求,必须是分组长度长度的倍数,AES加密数据块分组长度必须为128bit也就是16位,所以这块又涉及到一个填充问题,而这个填充方式可以分为PKCS7和PKCS5等方式,不得不说是真麻烦。
本文以CBC模式为例来介绍,CBC又有点特殊,它需要一个iv偏移量,iv不一样,结果也不一样所以更安全,这个偏移量必须和分组大小长度一样,也是16位,其实如何去生成iv和填充明文才是最麻烦的地方,但标准库里面并没有给出示例,我网上找了下,先看一个简单的实现:
1 | func AesCBCEncrypt(plainText []byte, key []byte) []byte { |
实际应用中,秘钥我们可以指定为固定位数,但是需要加密的内容往往是不固定长度的,所以需要做填充,同时在解密的时候就需要去除填充,这里总结了2种填充方法,一个是PKCS7,网上也有些文章称之为PKCS5,另一个是0填充。
1 | func PKCS7Padding(src []byte, blockSize int) []byte { |
解密的过程首先是要提取出iv,然后解密,最后去除填充得到明文,代码如下:
1 | func AesCBCDecrypt(cipherText []byte, key []byte) []byte { |
最后,咱们来看一个简单的使用示例:
1 | func main() { |
RSA非对称加密
RSA非对称加密需要一对秘钥,一个公钥,一个私钥,公钥加密之后私钥才能解密,私钥加密之后公钥才能解密,其最广泛的应用莫过于https、ssh,安全性高,但是速度相对较慢。
首先,我们得生成一对秘钥,方法有很多种,我们可以用工具生成,比如在Linux下面可以使用openssl命令生成:
1 | # 生成私钥 |
也可以使用一些工具生成,保存起来,值得一提的是这个秘钥的格式还有很多说法,这里暂不细说,如果遇到问题了,不妨留意一下。
Go的crypto库提供了一些方法来进行rsa的加密和解密操作,不过同样我们还得自己组装起来,先看一下加密:
1 | func RsaEncrypt(plainText []byte, keyPath string) []byte { |
然后是解密:
1 | func RsaDecrypt(cipherText []byte, keyPath string) []byte { |
综合示例:
1 | func main() { |
RSA加密每次的结果都不一样,安全性虽高,但是也有缺点,速度慢,而且加密的内容不能太大,最大不能超过秘钥的长度,比如说这个例子里面秘钥是2048位的,也就是256字节,如果超过了可能就需要你特殊处理了,比如分割成多段依次加密。
总之,在Go里面使用加密的话需要根据实际情况调整,不同加密方式的实现细节有很多不一样的地方,好在标准库大部分都实现了,只需要我们花点功夫研究一下咋去使用。