Go中使用加密算法




哈希算法

  1. md5

128bit,16字节

如:md5 (“hello world!”) = fc3ff98e8c6a0d3087d515c0473f8677 // 32位16进制数字

func Test(t *testing.T) {
   
	//方法一
	str := "hello world!"
	has := md5.Sum([]byte(str))
	md5str1 := fmt.Sprintf("%x", has) //将[]byte转成16进制
	t.Log(md5str1)

	//方法二
	w := md5.New()
	io.WriteString(w, str)
	md5str2 := fmt.Sprintf("%x", w.Sum(nil))
	t.Log(md5str2)
}



  1. SHA1

160bit,20字节

如:SHA1 (“hello world!”) = 430ce34d020724ed75a196dfc2ad67c77772d169 // 40位16进制数字

func Test(t *testing.T) {
   
	str := "hello world!"

	//产生一个散列值得方式是 sha1.New(),sha1.Write(bytes),然后 sha1.Sum([]byte{})。
	h := sha1.New()

	//写入要处理的字节。
	h.Write([]byte(str))

	//SHA1 值经常以 16 进制输出,例如在 git commit 中。
	t.Log(hex.EncodeToString(h.Sum(nil)))
}



  1. RIPEMD-160

160bit,20字节

如:RIPEMD-160 (“hello world!”) = dffd03137b3a333d5754813399a5f437acd694e5 // 40位16进制数字

func Test(t *testing.T) {
   
	str := "hello world!"

	h := ripemd160.New()
	h.Write([]byte(str))
	t.Log(hex.EncodeToString(h.Sum(nil)))
}



  1. SHA256

256bit,32字节

如:SHA256 (“hello world!”) = 7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9 // 64位16进制数字

func Test(t *testing.T) {
   
	str := "hello world!"

	// 第一种调用方法
	sum := sha256.Sum256([]byte(str))
	t.Logf("%x\n", sum)

	// 第二种调用方法
	h := sha256.New()
	io.WriteString(h,str)
	t.Log(hex.EncodeToString(h.Sum(nil)))
}

SHA256实现原理


SHA-256算法输⼊报⽂的最⼤⻓度不超过2^64 bit,输⼊按512bit分组进⾏处理,产⽣的输出是⼀个256bit的报⽂摘要。


SHA256算法包括以下⼏步:

  1. 附加填充⽐特
    对报⽂进⾏填充,使报⽂⻓度与448 模512 同余(⻓度=448 mod512),填充的⽐特数范围是1 到512,填充⽐特串的最⾼位为1,其余位为0。就是先在报⽂后⾯加⼀个 1,再加很多个0,直到⻓度满⾜mod512=448。为什么是448,因为448+64=512。第⼆步会加上⼀个64bit的原始报⽂的 ⻓度信息。
  2. 附加⻓度值
    将⽤64bit 表示的初始报⽂(填充前)的位⻓度附加在步骤1的结果后(低位字节优先)
  3. 初始化缓存
    使⽤⼀个256bit 的缓存来存放该散列函数的中间及最终结果。该缓存表示为:
    A=0x6A09E667
    B=0xBB67AE85
    C=0x3C6EF372
    D=0xA54FF53A
    E=0x510E527F
    F=0x9B05688C
    G=0x1F83D9AB
    H=0x5BE0CD19
  4. 处理512bit(16 个字)报⽂分组序列
    该算法使⽤了六种基本逻辑函数,由64 步迭代运算组成。每步都以256bit 缓存ABCDEFGH 为输⼊,然后更新缓存内容。每步使⽤⼀个32bit 常数值Kt 和⼀个32bit Wt。



  1. SHA512

512bit,64字节

如:SHA512 (“hello world!”) = db9b1cd3262dee37756a09b9064973589847caa8e53d31a9d142ea2701b1b28abd97838bb9a27068ba305dc8d04a45a1fcf079de54d607666996b3cc54f6b67c // 128位16进制数字

func Test(t *testing.T) {
   
	str := "hello world!"

	// 第一种调用方法
	sum := sha512.Sum512([]byte(str))
	t.Logf("%x\n", sum)

	// 第二种调用方法
	h := sha512.New()
	io.WriteString(h,str)
	t.Log(hex.EncodeToString(h.Sum(nil)))
}



加密模式

加密一般分为对称加密(Symmetric Key Encryption)和非对称加密(Asymmetric Key Encryption)。

对称加密又分为分组加密和序列密码。

分组密码,也叫块加密(block cyphers),一次加密明文中的一个块。是将明文按一定的位长分组,明文组经过加密运算得到密文组,密文组经过解密运算(加密运算的逆运算),还原成明文组。

序列密码,也叫流加密(stream cyphers),一次加密明文中的一个位。是指利用少量的密钥(制乱元素)通过某种复杂的运算(密码算法)产生大量的伪随机位流,用于对明文位流的加密。

解密是指用同样的密钥和密码算法及与加密相同的伪随机位流,用以还原明文位流。

分组加密算法中,有ECB,CBC,CFB,OFB这几种算法模式。

加密模式 解释
ECB 最基本的加密模式,也就是通常理解的加密,相同的明⽂将永远加密成相同的密⽂,⽆初始向量,容易受到密码本重放攻击,⼀般情况下很少⽤
CBC 明⽂被加密前要与前⾯的密⽂进⾏异或运算后再加密,因此只要选择不同的初始向量,相同的密⽂加密后会形成不同的密⽂,这是⽬前应⽤最⼴泛的模式。CBC加密后的密⽂是上下⽂相关的,但明⽂的错误不会传递到后续分组,但如果⼀个分组丢失,后⾯的分组将全部作废(同步错误)
CFB 类似于⾃同步序列密码,分组加密后,按8位分组将密⽂和明⽂进⾏移位异或后得到输出同时反馈回移位寄存器,优点最⼩可以按字节进⾏加解密,也可以是n位的,CFB也是上下⽂相关的,CFB模式下,明⽂的⼀个错误会影响后⾯的密⽂(错误扩散)。
OFB 将分组密码作为同步序列密码运⾏,和CFB相似,不过OFB⽤的是前⼀个n位密⽂输出分组反馈回移位寄存器,OFB没有错误扩散问题



对称加密

最常用的对称加密算法DES、3DES(TripleDES)和AES,常采用的填充⽅式是NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充。

加密算法要求明文需要按一定长度对齐,叫做块大小(BlockSize),比如8字节,那么对于一段任意的数据,加密前需要对最后一个块填充到8 字节,解密后需要删除掉填充的数据。

填充⽅式 解释
ZeroPadding 数据长度不对齐时使用0填充,否则不填充
PKCS7Padding 假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小
PKCS5Padding PKCS7Padding的子集,块大小固定为8字节

由于使用PKCS7Padding/PKCS5Padding填充时,最后一个字节肯定为填充数据的长度,所以在解密后可以准确删除填充的数据,而使用ZeroPadding填充时,没办法区分真实数据与填充数据,所以只适合以\0结尾的字符串加解密。



对称加密需要的填充函数

func PKCS5Padding(data []byte, blockSize int) []byte {
    
	padding := blockSize - len(data)%blockSize
	padtext := bytes.Repeat([]byte{
    byte(padding)}, padding)
	return append(data, padtext...)
}

func PKCS5UnPadding(data []byte) []byte {
    
	length := len(data)
	// 去掉最后⼀个字节 unpadding 次
	unpadding := int(data[length-1])
	return data[:(length - unpadding)]
}

func ZeroPadding(data []byte, blockSize int) []byte {
    
	padding := blockSize - len(data)%blockSize
	padtext := bytes.Repeat([]byte{
    0}, padding)
	return append(data, padtext...)
}

func ZeroUnPadding(data []byte) []byte {
    
	return bytes.TrimRightFunc(data, func(r rune) bool {
    
		return r == rune(0)
	})
}



  1. DES
//DES加密字节数组,返回字节数组
func DesEncrypt(originalBytes, key []byte) ([]byte, error) {
   
	block, err := des.NewCipher(key)
	if err != nil {
   
		return nil, err
	}
	originalBytes = PKCS5Padding(originalBytes, block.BlockSize())
	blockMode := cipher.NewCBCEncrypter(block, key)
	cipherArr := make([]byte, len(originalBytes))
	blockMode.CryptBlocks(cipherArr, originalBytes)
	return cipherArr, nil
}

//DES解密字节数组,
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值