描述:实现服务授权,通过对称加密算法AES和分组模式CFB(密文反馈模式)实现。目前的加密算法很多,包括对称加密,非对称加密,单向散列函数。下面来分析为什么采用这种方式实现。
Ⅰ.业务需求,明文承以下形式:
2018-08-08&&&&&xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&&&&&2018-12-12
当天时间 内容随意,不要出现 & 分隔符即可,一旦生成,不可更改 服务截至日期
密文解码后,其 &&&&& 之前的内容要与明文中 &&&&& 之前的内容完全相同,才能使用密文中的截至日期,保证授权成功。
Ⅱ.加密算法:
1.对称加密:
算法:
①DES:通过撞库的方式,曾被暴力破解
②3DES:实现3次des加密,第二次加密其实是解密,是为了兼容之前DES的加密算法,数据安全性是提高了,但是3次的加密导致效率低了
③AES:效率高,推荐使用
分组模式:
①ECB(电子密码本):对明文进行分组加密,若其中的一组被破解,其余的不言而喻,不安全
②CBC(密文分组链接模式):先对初始向量进行按位异或操作,再对明文分组1进行加密操作生成密文分组1,再将密文分组1以初始向量的形式操作。但是最后一组明文分组的长度未达到规定长度,需要进行补位
③CFB(密文反馈模式):与CBC类似,按位异或操作和加密操作的顺序交换,这样即使明文分组长度不够,也不用补位,符合业务需求
④OFB(输出反馈模式):不断对初始向量进行加密,导致明文中绿色的部分永远不会改变,密文的安全性降低
⑤CTR(计数器模式):只是对计数器进行加密,与④中的担心一样
2.非对称加密:
RSA:正因为担心网络传输的不安全性,怕密钥泄漏,才有了公钥和私钥的概念。服务授权不涉及密钥的网络传输。
3.单项散列函数
MD5,SHA1,SHA256,SHA512
只能加密,不能解密
代码如下:
//aes(加密算法) + CFB(分组模式) /* 加密 - 参数1:明文 - 参数2:密钥,aes规定密钥为16,24或32字节 - 参数3:初始向量,初始向量长度和明文分组相同,即16字节 */ func EncodeAesCFB(src, key, iv []byte) []byte { /* 1.加密算法 2.分组模式 3.明文和密文进行异或运算 */ block, _ := aes.NewCipher(key) stream := cipher.NewCFBEncrypter(block, iv) stream.XORKeyStream(src, src) return src } /* 解密 - 参数1:密文 - 参数2:密钥,aes规定密钥为16,24或32字节 - 参数3:初始向量,初始向量长度和明文分组相同,即16字节 */ func DecodeAesCFB(src, key, iv []byte) []byte { /* 1.加密算法 2.分组模式 3.明文和密文进行异或运算 */ block, _ := aes.NewCipher(key) stream := cipher.NewCFBDecrypter(block, iv) stream.XORKeyStream(src, src) return src } /* 服务授权时间加密 -参数1:服务到期时间 */ func GenerateCipher(dateString string) string{ //明文 plainText := time.Now().Format("2006-01-02")+"&&&&&skjdsahdfwieurjow;ilhfnskjvckkxja;skdfja;sdfhaghjuijnkvn;kjfn;ahfaiugjhwoij;qqwieuityeuir&&&&&"+dateString //密钥 key := "poiuytrewqpoiuytrewqpoiuytrewqqq" //初始向量 iv := "poiuytrewqpoiuyt" //加密 dst := EncodeAesCFB([]byte(plainText), []byte(key), []byte(iv)) //加密之后,有些字节不在acsii码中,会出现乱码。base64编码后会将字节缩短到64字节之内,防止乱码 rst := base64.StdEncoding.EncodeToString(dst) return rst } /* 获取密文中的服务到期时间 -参数1:密文 */ func GetDueTime(cipherText string) (string,error) { plainTextPrefix := time.Now().Format("2006-01-02")+"&&&&&skjdsahdfwieurjow;ilhfnskjvckkxja;skdfja;sdfhaghjuijnkvn;kjfn;ahfaiugjhwoij;qqwieuityeuir" key := "poiuytrewqpoiuytrewqpoiuytrewqqq" iv := "poiuytrewqpoiuyt" b, _ := base64.StdEncoding.DecodeString(cipherText) plainText := string(DecodeAesCFB(b, []byte(key), []byte(iv))) //密文中包含明文前缀,获取截至日期,否则返回错误 if plainText[:strings.LastIndex(plainText, "&&&&&")] == plainTextPrefix { dueTime := plainText[strings.LastIndex(plainText, "&&&&&")+len("&&&&&"):] return dueTime,nil }else{ return "",errors.New("incorrect code") } }