go实现服务授权

描述:实现服务授权,通过对称加密算法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")
	}
}

  

原文地址:https://www.cnblogs.com/asceticmonks/p/13267201.html