Java 企业级工具类全家桶-86-字符串散列摘要工具类 目录一、工具类功能二、所需环境三、方法与调用示例按需调用四、工具类源码可直接复制一、工具类功能面向字符串的 MD5/SHA-1/SHA-256/SHA-512 摘要支持加盐多轮迭代与恒时校验、统一小写十六进制输出口令的存与校验走 PBKDF2两类用途在入口上就分开。二、所需环境JDK 17或以上三、方法与调用示例按需调用方法序号1方法用途算出字符串 UTF-8 字节的 MD5拿到 32 位小写十六进制做内容指纹、缓存键、去重比对时一行搞定不用自己开MessageDigest方法定义public static String md5(String data)️入参解释public static String md5(待摘要字符串)返回值解释String32 个字符的小写十六进制摘要边界口径空串是合法输入结果恒为d41d8cd98f00b204e9800998ecf8427eWebhook 空 body 签名就吃这条只有null被拒抛IllegalArgumentException: 待摘要字符串不能为nullMD5 只做内容指纹别拿它存口令也别指望它抗碰撞方法示例md5(hello)拿到5d41402abc4b2a76b9719d911017c592md5()拿到d41d8cd98f00b204e9800998ecf8427emd5(null)抛IllegalArgumentException: 待摘要字符串不能为null方法序号2方法用途算出字符串的 SHA-1 摘要拿到 40 位小写十六进制对接只认 SHA-1 的老开放平台签名时直接用它方法定义public static String sha1(String data)️入参解释public static String sha1(待摘要字符串)返回值解释String40 个字符的小写十六进制摘要边界口径与md5一样空串合法结果是da39a3ee5e6b4b0d3255bfef95601890afd80709null抛IllegalArgumentException中文按 UTF-8 取字节同一个串在任何机器上结果一致新项目优先 SHA-256SHA-1 只用于兼容既有协议方法示例sha1(hello)拿到aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434dsha1()拿到da39a3ee5e6b4b0d3255bfef95601890afd80709空白输入也有固定摘要sha1(null)抛IllegalArgumentException: 待摘要字符串不能为null方法序号3方法用途算出字符串的 SHA-256 摘要拿到 64 位小写十六进制内容指纹、缓存键、接口签名的默认选择长度和强度都够用方法定义public static String sha256(String data)️入参解释public static String sha256(待摘要字符串)返回值解释String64 个字符的小写十六进制摘要边界口径空串合法结果是e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855null抛IllegalArgumentException它和hash(SHA-256, data)是同一个结果便捷入口只是省得写算法名方法示例sha256(hello)拿到2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824sha256(订单号 ORD-2026-0001)拿到c0016d8ab06b601747b99ab4d4df3c87433d82e95be7d62251b3bef7bdd7313a中文串不受机器语言环境影响sha256()拿到e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855方法序号4方法用途算出字符串的 SHA-512 摘要拿到 128 位小写十六进制需要更长的指纹比如把摘要当密钥材料再切分时用它方法定义public static String sha512(String data)️入参解释public static String sha512(待摘要字符串)返回值解释String128 个字符的小写十六进制摘要边界口径输出长度固定 128 个字符是 SHA-256 的两倍存库要留够字段宽度空串合法、null抛IllegalArgumentException与其它三个入口一致它仍是快哈希不是口令存储方案方法示例sha512(hello)拿到9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043sha512(hello).length()拿到128同一串的sha256(...)是 64 个字符sha512(null)抛IllegalArgumentException: 待摘要字符串不能为null方法序号5方法用途按算法名算摘要算法来自配置或协议字段时用它不用写一串 if算法名认md5、sha256、SHA-256、SHA256这些写法白名单之外的直接拒绝方法定义public static String hash(String algorithm, String data)️入参解释public static String hash(算法名, 待摘要字符串)返回值解释String小写十六进制摘要长度按算法固定边界口径算法名先去掉空白转大写再查别名SHA-256与sha256等价白名单只有 MD5/SHA-1/SHA-256/SHA-512SM3、MD2 这类抛IllegalArgumentException并列出支持范围不会退化成别的算法算法名为null或空白也抛IllegalArgumentException结果为小写十六进制对方给大写时要先统一再比方法示例hash(SHA-256, hello)与hash(sha256, hello)相同拿到truehash( md5 , hello)拿到5d41402abc4b2a76b9719d911017c592算法名带空白也能认hash(SM3, hello)抛IllegalArgumentException消息是「不支持的摘要算法: SM3仅支持 MD5/SHA-1/SHA-256/SHA-512」hash(null, hello)抛IllegalArgumentException: 摘要算法不能为null或空白方法序号6方法用途算「盐 内容」的多轮迭代摘要用作内容指纹或带前缀的校验值把盐混进指纹里别人拿一张彩虹表也反推不出原始内容方法定义public static String hashWithSalt(String algorithm, String data, String salt, int iterations)️入参解释public static String hashWithSalt(算法名, 待摘要字符串, 盐值, 迭代轮数)返回值解释String小写十六进制摘要长度按算法固定边界口径首轮是digest(salt || data)之后每轮把上一轮的字节再喂给同一算法iterations给 1 就是单轮同样的入参每次都得到同一个值可复现适合当缓存键盐为null或空白抛IllegalArgumentException这里没有「无盐」这一档轮数小于 1 抛IllegalArgumentException并带上当前的值这不是口令哈希方案没有 PBKDF2 的成本抬升存口令请用方法8方法示例hashWithSalt(SHA-256, hello, salt, 5)拿到3f6f10b86507ff979595b8274dbdbe1fcbe805b11ea708f10c1a534f9e40965a同一个入参把轮数改成 1拿到cd31b3b98ece60cb739c0bf770b2de892ae0ad133f645513c3d83f08757a843a与 5 轮的结果完全不同连调两次 5 轮两次结果相同拿到true只把盐换成 “other”拿到2025601090de8401b5482d3c7ea4aa0a0b48605fc4824e8b7c554d34e31b9994hashWithSalt(SHA-256, hello, , 5)抛IllegalArgumentException: 盐值不能为null或空白hashWithSalt(SHA-256, hello, salt, 0)抛IllegalArgumentException: 迭代次数必须大于等于1当前为0方法序号7方法用途校验加盐迭代摘要是否与预期一致结果是一个boolean比对走常量时间实现不用自己写equals也不担心被计时侧信道利用方法定义public static boolean verifyWithSalt(String algorithm, String data, String salt, int iterations, String expected)️入参解释public static boolean verifyWithSalt(算法名, 待校验字符串, 盐值, 迭代轮数, 预期摘要)返回值解释boolean一致返回true不一致返回false边界口径预期值容忍大小写与首尾空白大写摘要串照样过轮数、盐、算法任一对不上就是false不会抛异常预期值为null或空白属于入参非法抛IllegalArgumentException计算口径完全跟着方法6方法示例verifyWithSalt(SHA-256, hello, salt, 5, expected)预期值就是方法6 的结果拿到true把预期值传成全大写拿到true预期值前后各加两个空格再验拿到true校验时把轮数改成 4去比 5 轮的结果拿到falseverifyWithSalt(..., )预期摘要传空白抛IllegalArgumentException: 预期摘要不能为null或空白方法序号8方法用途生成口令哈希串随机盐 PBKDF2-HMAC-SHA256输出自描述的$pbkdf2-sha256$迭代次数$盐$哈希注册时一行存进去登录时不用再记当初用了什么盐和轮数方法定义public static String hashPassword(String rawPassword)️入参解释public static String hashPassword(明文口令)返回值解释String口令哈希串默认迭代下总长 91 个字符边界口径默认 60 万次迭代、单次约几百毫秒是 CPU 密集操作只在注册与改密时调别放进请求主链路或循环里盐随机生成同一个口令两次调用得到的串不同但各自都能验通过它是PasswordHashUtils.hash(String)的轻量入口两边同格式、可互相校验要自定义盐长度或派生长度就用PasswordHashUtils口令为null或空串抛IllegalArgumentException方法示例hashPassword(Passw0rd!)拿到以$pbkdf2-sha256$600000$打头、总长91字符的串同一口令连调两次两个串相同拿到false因为盐是随机的hashPassword(null)抛IllegalArgumentException: 口令不能为nullhashPassword()抛IllegalArgumentException: 口令不能为空串方法序号9方法用途生成口令哈希串并自己指定迭代次数压参数或跑测试时把成本降下来迭代次数写在串里日后调高轮数也不影响老串验证方法定义public static String hashPassword(String rawPassword, int iterations)️入参解释public static String hashPassword(明文口令, 迭代次数)返回值解释String口令哈希串迭代次数编在串的第 2 段边界口径迭代次数必须落在[1000, 10000000]区间越界抛IllegalArgumentException消息带当前值和「生产建议使用600000」的提示生产直接用默认值小轮数只适合测试指定轮数生成的串与方法8 同格式都能被方法10 验过方法示例hashPassword(Passw0rd!, 10000)拿到以$pbkdf2-sha256$10000$打头的串hashPassword(Passw0rd!, 1)抛IllegalArgumentException消息是「迭代次数必须落在 [1000, 10000000] 区间当前为1生产建议使用600000」hashPassword(Passw0rd!, 100000000)抛IllegalArgumentException消息同样带区间与当前值verifyPassword(Passw0rd!, hashPassword(Passw0rd!, 20000))拿到true方法序号10方法用途校验明文口令与库里的口令哈希串是否匹配算法、轮数、盐都从串里解析登录链路只要交出口令和存串不用把当初的参数另外存在某处方法定义public static boolean verifyPassword(String rawPassword, String storedHash)️入参解释public static boolean verifyPassword(待校验口令, 库中口令串)返回值解释boolean匹配为true口令不对为false边界口径口令错一个字符、空口令、null口令统一收敛成false不抛异常也不区分原因免得给攻击者提示只有串本身格式非法被截断、不是这个格式、迭代次数越界才抛IllegalArgumentException消息写出实际拿到的串每次验证都要跑完串里记录的迭代次数登录接口要按这个成本限流方法示例verifyPassword(Passw0rd!, storedHash)口令正确拿到true末尾一个字符改成?拿到false传空口令与null口令拿到的都是falseverifyPassword(a, $pbkdf2)抛IllegalArgumentException消息是「口令哈希串格式不合法应为p b k d f 2 − s h a 256 pbkdf2-sha256pbkdf2−sha256迭代数盐 盐盐哈希实际为: $pbkdf2」方法序号11方法用途只判断一段字符串是不是口令哈希格式不做任何派生计算导入历史数据、迁移前挑出没升级过的记录时用一眼分得清口令串和普通摘要方法定义public static boolean isPasswordHashFormat(String storedHash)️入参解释public static boolean isPasswordHashFormat(待判断字符串)返回值解释boolean是该格式返回true边界口径null、空串、MD5/SHA 摘要串都返回false不抛异常只看格式不保证这串真能验过某个口令判定口径与PasswordHashUtils.isStoredFormat一致方法示例isPasswordHashFormat(hashPassword(a))拿到trueisPasswordHashFormat(sha256(a))拿到false普通摘要串不是口令格式isPasswordHashFormat(null)拿到false传空串也是false四、工具类源码可直接复制领取方式 关注点赞收藏私信回复「java工具类」可领取100个工具类「Java企业级工具类全家桶1-100」的完整源码 工具类已调试通过复制粘贴即可使用省时省力 可保存到自己网盘永久有效觉得对您有帮助麻烦点点关注啦您的关注是我创作的最大动力~