阅读 113

Golang封装加盐和加密次数的MD5函数

最近在使用Gin重构之前用SpringBoot写的后台程序,数据库中保存的密码是加了盐并经过两次hash的MD5值,之前SpringBoot是调用的Shiro进行两次MD5运算。查了一圈发现Golang的MD5工具库并没有提供加盐、加密次数的封装,并且也没有博客提及,所以这里记录一下自己封装的带加盐和加密次数的MD5函数

Golang中使用MD5库

Golang自带的crypto加密库中有MD5函数的实现,主要使用方式有两种,一种是调用write将要计算的byte数组提前写入block块中,调用sum时传入nil;二是直接将byte数组传入sum函数,如下所示:

package utils import ( "crypto/md5" "encoding/hex" ) // 方式一通过Write传参 func MD5(str string) string { b := []byte(str) h := md5.New() h.Write(b) return hex.EncodeToString(h.Sum(nil)) } // 方式二通过Sum传参 func MD5_2(str string) string { b := []byte(str) h := md5.New() return hex.EncodeToString(h.Sum(b)) } 复制代码

若要加盐的话,在第一种方式的基础上再把salt給write进去,如下所示:

func MD5_SALT(str string, salt string) string { b := []byte(str) s := []byte(salt) h := md5.New() h.Write(s) // 先写盐值 h.Write(b) return hex.EncodeToString(h.Sum(nil)) } 复制代码

错误的多次加密封装

查到MD5函数的加盐使用后,就想当然的以为多次加密应该就是循环加盐的过程,调用下面的封装后发现算出来的盐值不对,网上也没找到多次加密的文章,所以就去找了SpringBoot中的封装。

// 错误的加盐并多次加密 func MD5_SALT_MULT(str string, salt string, times int) string { b := []byte(str) s := []byte(salt) h := md5.New() var res []byte for i := 0; i < times; i++ { h.Write(s) h.Write(b) res = h.Sum(nil) b = res } return hex.EncodeToString(res) } 复制代码

Java加盐并多次加密的MD5函数

找了找以前的SpringBoot项目,发现当时调用了Shiro框架的MD5封装,只需要将盐值、加密次数传入SimpleHash函数就行了,当时并没思考后面是怎么运算的。

import org.apache.shiro.crypto.RandomNumberGenerator; import org.apache.shiro.crypto.SecureRandomNumberGenerator; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.util.ByteSource; public class PasswordHelper {     //随机字符串生成器,用于生成盐值     private RandomNumberGenerator numberGenerator = new SecureRandomNumberGenerator();     //哈希散列算法——md5     public static final String ALGORITHM_NAME = "md5";     //散列次数2     public static final int HASH_ITERATION = 2;     /**      *  加密用户      * @param user 用户,用户名(name)、密码(pwd)、盐\加密因子(salt)      */     public String encryptPassword(String password){         if (password == null || "".equals(password))             return;         //生成加密因子,保存盐。         String salt = numberGenerator.nextBytes().toHex();         //加密密码 SimpleHash(算法名,密码,盐的byte,次数).toHex()         String newPassword = new SimpleHash(ALGORITHM_NAME, password, salt, HASH_ITERATION).toHex();         //更新密码         return newPassword;     } } 复制代码

通过 SimpleHash函数向下找具体的实现,SimpleHash的核心代码如下,这才发现原来salt只用了一次,并且每次运算后还要调用rest函数清空digest中的block块,知道了具体过程后就是把这段Java代码翻译成Golang代码即可

package org.apache.shiro.crypto.hash; public class SimpleHash extends AbstractHash {     protected byte[] hash(byte[] bytes, byte[] salt, int hashIterations) throws UnknownAlgorithmException {         MessageDigest digest = this.getDigest(this.getAlgorithmName());         if (salt != null) {             digest.reset();             digest.update(salt);         }         byte[] hashed = digest.digest(bytes);         int iterations = hashIterations - 1;         for(int i = 0; i < iterations; ++i) {             digest.reset();             hashed = digest.digest(hashed);         }         return hashed;     } } 复制代码

用Golang实现加盐并多次加密的MD5函数

Java中的MessageDigest对象和Golang的hash结构体可以看作是等价的,都有rest函数,只不过Java通过调用digest函数运算hash值而Golang通过调用Sum函数运算,只需要将上面的Java代码进行简单的翻译就行了。最终封装如下:

package utils import ( "crypto/md5" "encoding/hex" ) func MD5V(str string, salt string, iteration int) string {     b := []byte(str)     s := []byte(salt) h := md5.New() h.Write(s) // 先传入盐值,之前因为顺序错了卡了很久 h.Write(b)         var res []byte res = h.Sum(nil) for i := 0; i < iteration-1; i++ { h.Reset() h.Write(res) res = h.Sum(nil) } return hex.EncodeToString(res) }


作者:Monkey_D_Newdun
链接:https://juejin.cn/post/7056324966005866504


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐