package com.monitor.util; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; public class SHAEncrypt { /** * 生成SALT的数组(86) */ private final String[] SALT_ARR = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", "-", "*", "/", "'", ":", ";", ">", "<", "~", "!", "@", "#", "$", "%", "^", "&", "(", ")", "{", "}", "[", "]", "|" }; /** * 循环加密次数 */ private final int ENCODE_COUNT = 1000; /** * 加密算法类型 */ private final String ENCODE_TYPE = "SHA-256"; /** * SALT长度 */ private final int SALT_LENGTH = 16; /** * getBytes时指定使用的字符集 */ private final String CHAR_SET = "UTF-8"; /** * 对明文密码进行SSHA-256加密,加密步骤如下: <br> * 1. 生成随机salt值 <br> * 2. 明文密码变形:前后各补4位0 <br> * 3. 连接salt值: 将salt分成前8位temp1和剩余部分temp2,以temp2+transformedPwd+temp1的形式连接 <br> * 4. 对连接后的字串进行多次SHA-256加密<br> * 5. 对加密后的密文右移6位<br> * 6. 将salt值转换成字节数组(utf-8)再转换成16进制字符串<br> * 7. 将转换后的salt值作左移4位变形<br> * 8. 连接移位后的密文和移位后的变形salt值字串<br> * 9. 对连接字串右移8位作为最终加密结果<br> * * @param pwd * 密码明文 * @return 加密后的密码 */ public String encryptPwd(String pwd) { String ret = ""; String salt = this.genSalt(); ret = this.encryptPwdWithSalt(pwd, salt); return ret; } /** * 对明文密码进行SSHA-256加密,加密步骤如下: <br> * 1. 明文密码变形:前后各补4位0 <br> * 2. 连接salt值: 将salt分成前8位temp1和剩余部分temp2,以temp2+transformedPwd+temp1的形式连接 <br> * 3. 对连接后的字串进行多次SHA-256加密<br> * 4. 对加密后的密文右移6位<br> * 5. 将salt值转换成字节数组(utf-8)再转换成16进制字符串<br> * 6. 将转换后的salt值作左移4位变形<br> * 7. 连接移位后的密文和移位后的变形salt值字串<br> * 8. 对连接字串右移8位作为最终加密结果<br> * * @param pwd * 明文密码 * @param salt * 用于加密的salt值 * @return */ private String encryptPwdWithSalt(String pwd, String salt) { String ret = ""; try { String transformedPwd = this.transform(pwd, 4); // 将salt分成前8位temp1和剩余部分temp2 // 以temp2+transformedPwd+temp1的形式连接 String joinStr = this.joinSaltAndPwd(salt, transformedPwd); String encodePwd = this.encodeJoinStr(joinStr); String rightMovedPwd = this.rightMove(encodePwd, 6); String hexStrSalt = this.bytes2Hex(salt.getBytes(CHAR_SET)); String leftMovedHexStrSalt = this.rightMove(hexStrSalt, -4); ret = this.rightMove(rightMovedPwd + leftMovedHexStrSalt, 8); } catch (Exception e) { ret = ""; e.printStackTrace(); } return ret; } /** * 对明文/密文进行验证,检查是否一致 验证步骤如下: <br> * 1. 从原密文中获取通过逆运算获取salt字串 <br> * 2. 对明文密码使用salt字串再次进行加密 <br> * 3. 两个密文是否一致 <br> * * @param pwd * 明文密码 * @param encPwd * 密文密码 * @return 校验结果 */ public boolean validatePwd(String pwd, String encPwd) { if (null == encPwd) { return false; } boolean ret = false; String salt = this.getSaltFromEncryptedPwd(encPwd); ret = encPwd.equals(encryptPwdWithSalt(pwd, salt)); return ret; } /** * 从密文密码中通过逆运算获取加密时使用到的salt字串 <br> * 获取步骤如下: <br> * 1. 对密文左移8位 <br> * 2. 从尾部截取变形后的salt字串 <br> * 长度为2倍原salt字串长度(因为转为16进制字节数组字串时长度会加倍) <br> * 3. 对salt值的16进制字节数组字符串右移4位 <br> * 4. 将变形后的salt值从16进制字节数组字符串还原成原来的字符串形式 <br> * * @param encPwd * 密文密码 * @return 加密时使用的salt字串,获取出错则返回"" */ private String getSaltFromEncryptedPwd(String encPwd) { String ret = ""; try { String leftMoved = this.rightMove(encPwd, -8); int hexSaltLength = SALT_LENGTH * 2; if(encPwd.length()<hexSaltLength){ // 加密密码长度比16进制字节数组字串的salt值短,不可能获取得到正确的salt值 return ""; } String hexSalt = this.rightMove(leftMoved.substring(encPwd.length() - hexSaltLength, encPwd.length()), 4); ret = new String(this.hex2Bytes(hexSalt), CHAR_SET); } catch (Exception e) { ret = ""; e.printStackTrace(); } return ret; } /** * * 获得随机SALT值 * * @return 返回一个包含字母、数字、特殊字符的16位随机数 */ private String genSalt() { StringBuffer result = new StringBuffer(); Random r = new Random(); int temp = 0; for (int i = 0; i < this.SALT_LENGTH; i++) { temp = r.nextInt(this.SALT_ARR.length); result.append(this.SALT_ARR[temp]); } return result.toString(); } /** * 密码变形(前后补N位0) * * @param pwd * 密码原文 * @param n * 补0的个数 * @return 返回一个密码前后补N位0的字符串 */ private String transform(String pwd, int n) { String toTransform = null == pwd ? "" : pwd; StringBuffer temp = new StringBuffer(); for (int i = 0; i < n; i++) temp.append("0"); return temp.toString() + toTransform + temp.toString(); } /** * * 把指定字符串右移N位,若N<0则为左移 * * @param src * 源字符串 * @param n * 右移的位数 * @return 返回一个右移N位的字符串 */ private String rightMove(String src, int n) { if (src == null || src.length() == 0) { return src; } boolean isRight = true; int absN = n; if (n < 0) { isRight = false; absN = -n; } int cnt = absN > src.length() ? absN % src.length() : absN; if (0 == cnt) { return src; } if (isRight) { // 右移cnt位 String temp1 = src.substring(src.length() - cnt, src.length()); String temp2 = src.substring(0, src.length() - cnt); return temp1 + temp2; } else { // 左移cnt位 String temp1 = src.substring(0, cnt); String temp2 = src.substring(cnt, src.length()); return temp2 + temp1; } } /** * * 把对应的随机数分成2部分,前半部分8个字符,调换顺序后把变形密码加到中间 * * @param pwd * 变形密码 * @param salt * 对应的随机数 * @return 返回一个随机数与变形密码连接的字符串 */ private String joinSaltAndPwd(String salt, String pwd) { if(salt.length()!=SALT_LENGTH){ // salt值的长度与给定的不符(校验的时候可能会出现) // 返回pwd+salt return pwd+salt; } String temp1 = salt.substring(0, 8); String temp2 = salt.substring(8, salt.length()); return temp2 + pwd + temp1; } /** * * 使用加密算法进行多次加密 * * @param joinStr * 连接字符串 * @return 返回一个多次加密后的字符串 */ private String encodeJoinStr(String joinStr) { if (joinStr == null) return null; String temp = joinStr; for (int i = 0; i < this.ENCODE_COUNT; i++) { temp = this.encrypt(temp); } return temp; } /** * 把字节数组输出成16进制字符串 * * @param bts * @return */ private String bytes2Hex(byte[] bts) { StringBuffer des = new StringBuffer(); String tmp = null; for (int i = 0; i < bts.length; i++) { tmp = (Integer.toHexString(bts[i] & 0xFF)); if (tmp.length() == 1) { des.append("0"); } des.append(tmp); } return des.toString(); } /** * 把16进制字符串输出成字节数组 * * @param hexStr * @return */ private byte[] hex2Bytes(String hexStr) { if ((hexStr.length() % 2) != 0) { return new byte[] {}; } byte[] ret = new byte[hexStr.length() / 2]; for (int i = 0; i < hexStr.length() / 2; i++) { ret[i] = (byte) (Long.decode("0x" + hexStr.substring(i * 2, i * 2 + 2)) & 0xFF); } return ret; } /** * * 利用SHA-256对源字符串进行加密 * * @param src * @return 返回加密串,注:本例中,空串表示加密失败 */ private String encrypt(String src) { // 源字符串转换成byte数组 try { byte[] btSource = src.getBytes(CHAR_SET); // 此处选择了SHA-256加密算法,实际可选的算法有"MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512" MessageDigest md = MessageDigest.getInstance(this.ENCODE_TYPE); md.reset(); md.update(btSource); String result = bytes2Hex(md.digest()); // to HexString return result; } catch (NoSuchAlgorithmException e) { return ""; } catch (UnsupportedEncodingException e) { return ""; } } public static void main(String args[]) throws Exception { SHAEncrypt demo = new SHAEncrypt(); String str = "12test中文濲騃"; long startTime = System.currentTimeMillis(); String encPwd = demo.encryptPwd(str); System.out.println("encrypt time costs:" + (System.currentTimeMillis() - startTime)); System.out.println("encrypted pwd:" + encPwd + ",length:" + encPwd.length()); System.out.println(demo.validatePwd(str, encPwd)); System.out.println(new String(demo.hex2Bytes(encPwd), "UTF-8")); } }
发表评论
-
遍历文件夹查找字符串并写入文件小例子
2012-11-22 10:31 943package com.zeng.find; im ... -
dd/MM/yyyy:HH:mm:ss +0800时间格式的转换
2012-11-19 10:23 3213SimpleDateFormat sdf1 = new ... -
各种排序算法及其java程序实现
2012-09-28 14:39 930各种排序算法:冒择 ... -
Java排序算法之 —— 插入排序
2012-09-27 10:33 894package algorithm.sort; / ... -
Java排序算法之 —— 选择排序
2012-09-27 10:32 921package algorithm.sort; ... -
Java排序算法之 —— 归并排序
2012-09-27 10:31 1316package algorithm.sort; / ... -
Java排序算法之 —— 冒泡排序
2012-09-27 10:29 901package algorithm.sort; ... -
Java线程超时控制的实现
2012-09-27 10:20 1509一.何时需要超时控制 超时控制一般使用阻塞时间比较 ... -
随机生成由字母和数字组成的字符串
2012-08-23 16:25 991private final static String[ ... -
java图片压缩、解压缩
2012-08-23 15:57 1646/** * 对图像进行压缩 * @param imag ...
相关推荐
java代码编写的密码加密类,可以解密。根据自己需求改变秘钥,更安全。windows和Linux环境密文不一致问题解决方案见我的博客https://blog.csdn.net/yang1393214887/article/details/83411051#comments
排列码是一种在信息安全领域常用的编码方式,主要用于数据的加密与解密。它的基本思想是将原始数据通过特定的算法进行编码,使得数据在传输或存储过程中不易被破解,增加了数据的安全性。在Java中实现排列码,我们...
"对密码进行加密解密" 在本篇文章中,我们将讨论如何实现对登录密码的加密解密,以确保项目安全。为了实现这一点,我们将使用 Java 语言和 DES 加密算法来实现密码的加密和解密。 首先,我们需要了解什么是 DES ...
本示例通过Java实现了字符串的加密与解密功能,采用DES加密算法,提供了基本的加密解密功能及字符串与十六进制之间的转换。这种实现方式适用于简单的加密需求,但对于更复杂的安全场景,建议考虑使用更先进的加密...
总的来说,这个主题涵盖了密码学的基本概念,加密算法的原理,以及如何通过GUI实现用户友好的加密和解密操作。对于IT从业者,尤其是那些关注数据安全和隐私保护的人员,理解和掌握这些知识点是非常必要的。通过学习...
3. **密码器创建与初始化**:`Cipher`类负责实际的加密和解密操作。`Cipher.getInstance("AES")`获取一个AES密码器实例,然后根据操作模式(加密或解密)进行初始化。例如,`cipher.init(Cipher.ENCRYPT_MODE, key)`...
Java文本加密解密是计算机编程领域中的一个重要主题,特别是在数据安全和信息安全方面。在这个课程设计中,我们将使用Java语言来实现一个简单的文本加解密系统,该系统具有图形用户界面(GUI),使得用户能够方便地...
总结来说,Java编程实现的同步序列密码加密解密系统是一种高效且灵活的解决方案,适用于需要实时加密大量数据的场景。理解其工作原理和实现细节,对于提升软件的安全性和合规性至关重要。在开发过程中,应始终关注...
Java和JavaScript之间的DES加密解密是信息安全领域中的一个重要话题,主要涉及到数据的保护和通信的安全。DES(Data Encryption Standard)是一种古老的对称加密算法,尽管它在安全性上已不被视为最佳选择,但在某些...
在Java编程环境中,处理文件的压缩与解压缩是常见的任务,而涉及到安全性,加密和解密就显得尤为重要。本文将详细讲解如何使用Java实现ZIP压缩包的加密与解密。 首先,我们需要理解加密的基本概念。加密是将明文...
Java加密解密工具包,通常用于保护敏感数据的安全,防止未经授权的访问或篡改。这个名为"JCT"的工具包提供了丰富的功能,使得开发者在Java应用中集成加密和解密操作变得更加简单。下面我们将详细探讨Java加密的相关...
java实现MD5加密解密算法,java源代码~
Java中的AES128加密解密是信息安全领域中常见的数据保护技术。AES,全称Advanced Encryption Standard,是一种块密码标准,被广泛应用于各种场景,包括网络传输、存储数据加密等。128位是AES的一个关键参数,表示...
这个程序可以帮助用户轻松地加密和解密文本,同时展示了如何在Java中结合基本的密码学原理和图形用户界面设计。在实际应用中,可以考虑增加更多的安全措施,如使用更复杂的密钥生成和管理机制,以及支持其他字符集和...
例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码...
Java加密解密工具是开发过程中不可或缺的部分,尤其是在处理敏感数据时,确保数据的安全性至关重要。在Java中,我们可以使用各种库和内置API来实现加密和解密操作。本篇文章将深入探讨Java加密解密的核心概念、常用...
在实际开发中,可以利用Java提供的API和第三方库来构建文件加密工具,简化加密解密流程,例如Apache Commons Codec库中的Base64编码,便于在程序中处理二进制数据。 总结,Java文件加密和解密涉及多种加密算法、...
java实现md5 加密解密(在网络中MD5是著名的不可逆算法,但是如果知道MD5的加密的字符串 则可以通过自己的加密算法对明文进行加密,对加密后的密文与字符串匹配; 匹配成功,表示找到明文;但是此程序的时间耗费较高!仅...
标题和描述均提到了“Java加密解密简单实现”,这主要涵盖了消息摘要、单匙密码体制(DES)、数字签名(RSA)以及非对称密匙密码体制(公匙体系)等核心概念及其在Java中的应用。 ### 消息摘要 消息摘要是一种用于...
Java加密解密技术在软件开发中扮演着至关重要的角色,特别是在数据安全领域。3DES(Triple Data Encryption Standard)是一种常见的加密算法,它基于DES(Data Encryption Standard)并对其进行了加强,提高了安全性...