| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> PHP知识库 -> java解密加密MD5 -> 正文阅读 |
|
[PHP知识库]java解密加密MD5 |
ava实现加密与解密
????纵观密码学的发展史,它共经历了三个阶段,分别是手工加密阶段、机械加密阶段和计算机加密阶段。手工加密阶段最为漫长,期间孕育了古典密码,这为后期密码学的发展奠定了基础。机械工业革命发展的同时促进着各种科学技术的进步,密码学也不例外。加之两次世界大战,更加促进了密码学的飞速发展,密码学由此进入现代密码学阶段。尽管如此,在这一阶段的密码学仍旧未能摆脱古典密码学的影子,加密与解密操作均依赖于语言学的支持,转轮密码机Enigma的发明与破解更是将这一特点发挥到了极致。随着数据理论逐步介入,密码学逐渐成为一门学科,而非一门艺术。进入计算机加密阶段后,密码学应用不再局限于军事、政治和外交领域,逐步扩大到商务、金融和社会的其他领域。密码学的研究和应用已大规模扩展到了民用方面。 ??????密码学主要包含两个分支:密码编码学和密码分析学。密码编码学针对于信息如何隐藏;密码分析学针对于信息如何破译。编码学与分析学相互影响,共同促进密码学的发展。 ???????古典密码是现代密码的基础,移位和替代是古典密码最常用、最核心的两种加密技巧。由此,古典密码主要分为移位密码和替代密码。例如,凯撒密码就是替代密码的典范。替代密码其分支众多,包含单表替代密码、同音替代密码、多表替代密码和多字母替代密码。移位和替代技巧仍是现代密码学最常用的两种加密手段。 二、现代密码学中的柯克霍夫原则 即使非数学上不可破解,系统也应在实质(应用)程度上无法破解。 系统内不应含任何机密物,即使落入敌人手中也不会造成困扰。 密钥必须易于沟通和记忆,而无需写下,且双方可以很容易地改变密钥。 系统应可以用于电讯。 系统应可以携带,不应需要两个人或两个人以上才能使用(应只要一个人就能使用)。 系统应容易使用,不致让使用者的脑力过分操劳,也无须记得长串的规则。 三、密码体制划分 ??????从密码体制上划分,现代密码学工分为两种密码体制:堆成密码体制和非对称密码体制。对称与非对称的差别源于加密密钥和解密密钥是否对称,即加密密钥与解密密钥是否相同(对称)。 ??????在对称密码体制中,加密与解密操作使用相同的密钥,我们把这个密钥称为秘密密钥。DES、AES算法都是常用的对称密码算法。流密码实现简单,对环境要求低,适用于手机平台的加密,广泛应用于军事、外交领域。RC4算法就是典型的流密码算法。流密码的理论、算法受限于国家安全因素未能公布。分组密码在这一点上与流密码恰恰相反,其理论,算法公开,分类众多。DES、AES算法主要的对称密码算法均属于分组密码。分组密码共有5中工作模式:电子密码本模式(ECB)、密文链接模式(CBC)、密文反馈模式(CFB)、输出反馈模式(OFB)、计数器模式(CTR)。分组密码会产生短块,关于短块的处理方法有填充法、流密码加密法、密文挪用技术。 ????????在非对称密码体制中,加密与解密操作使用不同的密钥。对外公开的密钥,称为公钥;对外保密的密钥,称为私钥。用公钥加密的数据,只能用私钥解密;反之,用私钥加密的数据,只能用公钥解密。RSA算法是常用的非对称密码算法。非对称密码体制同时支持数字签名技术,如RSA、DSA都是常用的数字签名算法。 ???????散列函数可以有效地确保数据完整性,其是一项消息认证技术。常用的散列函数算法有MD5、SHA、Mac。散列函数也是数字签名技术中最重要的技术环节。数字签名离不开非对称密码体制,其私钥用于签名,公钥用于验证。基于数字签名的不可伪造性,数字签名技术成为5种安全服务中数据完整性服务、认证性服务和抗否认性服务的核心技术。通信双方只有一方提供数字签名的认证方式称为单向认证,通信双方都提供数字签名的认证方式称为双向认证。一般网银系统多采用单向认证方式,而要求较高的网银交易则都采用双向认证方式。 ???????PKI和PGP是现代网络安全技术领域的两把锁。目前电子商务、电子政务使用PKI技术来确保平台安全性。PGP则多用于电子邮件、文件等的数据签名与加密。 ???今天给大家介绍一下普遍了解到的加密解密算法MD5 ????MD5算法是典型的消息摘要算法,其前身有MD2、MD3和MD4算法,它由MD4、MD3、MD2算法改进而来。不论是哪一种MD算法,它们都需要获得一个随机长度的信息并产生一个128位的信息摘要。如果将这个128位的二进制摘要信息换算成十六进制,可以得到一个32位(每4位二进制数转换为1位十六进制数)的字符串,故我们见到的大部分MD5算法的数字指纹都是32位十六进制的字符串,如本章开篇中,MySQL下载页上的数字指纹(MD5: 5a077abefee447cbb271e2aa7f6d5a47)就是32位的十六进制字符串。现在,各大主流计算机语言均支持MD5算法。 ??????虽然,MD5算法漏洞越来越多,已不再安全,但至今我们仍没有看到它的下一版本——MD6算法的出现。或许,同样基于MD4算法改进而来的SHA算法将会是MD系列算法的主要替代者。 让我们一同回顾一下MD算法家族的发展历史。 1. MD2算法 ???????1989年,著名的非对称算法RSA发明人之一——麻省理工学院教授罗纳德·李维斯特(Ronald L. Rivest)开发了MD2算法。这个算法首先对信息进行数据补位,使信息的字节长度是16的倍数。再以一个16位的检验和作为补充信息追加到原信息的末尾。最后根据这个新产生的信息计算出一个128位的散列值,MD2算法由此诞生。 ???????有关MD2算法详情请参见RFC 1319(http://www.ietf.org/rfc/rfc1319.txt)。 2. MD4算法 ????????1990年,罗纳德·李维斯特教授开发出较之MD2算法有着更高安全性的MD4算法。在这个算法中,我们仍需对信息进行数据补位。不同的是,这种补位使其信息的字节长度加上448个字节后能成为512的倍数(信息字节长度mod 512 = 448)。此外,关于MD4算法的处理与MD2又有很大差别。但最终仍旧是会获得一个128位的散列值。MD4算法对后续消息摘要算法起到了推动作用,许多比较有名的消息摘要算法都是在MD4算法的基础上发展而来的,如MD5、SHA-1、RIPE-MD和HAVAL算法等。 ???????有关MD4算法的详情请参见RFC 1320(http://www.ietf.org/rfc/rfc1320.txt)。 ???????著名开源P2P(Peer-To-Peer,点对点)下载软件EMule(http://www.emule.com)所使用的消息摘要算法正是经过改良后的MD4算法。该算法用于对文件分块后做消息摘要,以验证其文件的完整性。 3. MD5算法 ????????1991年,继MD4算法后,罗纳德·李维斯特教授开发了MD5算法,将MD算法推向成熟。MD5算法经MD2、MD3和MD4算法发展而来,算法复杂程度和安全强度大大提高。但不管是MD2、MD4还是MD5算法,其算法的最终结果均是产生一个128位的消息摘要,这也是MD系列算法的特点。MD5算法执行效率略次于MD4算法,但在安全性方面,MD5算法更胜一筹。随着计算机技术的发展和计算水平的不断提高,MD5算法暴露出来的漏洞也越来越多。MD5算法已不再适合安全要求较高的场合使用。 有关MD5算法的详情请参见RFC 1321(http://www.ietf.org/rfc/rfc1321.txt),其中包含了MD2、MD4和MD5三种算法的C语言版实现。 Java代码实现如下 /** ?* 对字符串md5加密 ?* ?* @param str ?* @return ?*/ import java.security.MessageDigest; public static String getMD5(String str) { ?try { ?// 生成一个MD5加密计算摘要 ?MessageDigest md = MessageDigest.getInstance("MD5"); ?// 计算md5函数 ?md.update(str.getBytes()); ?// digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符 ?// BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值 ?return new BigInteger(1, md.digest()).toString(16); ?} catch (Exception e) { ?throw new SpeedException("MD5加密出现错误"); ?} } MD5加密解密类——MyMD5Util,代码如下 package com.zyg.security.md5; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Arrays; public class MyMD5Util { ? ?private static final String HEX_NUMS_STR="0123456789ABCDEF"; ?private static final Integer SALT_LENGTH = 12; ? ?/** ?* 将16进制字符串转换成字节数组 ?* @param hex ?* @return ?*/ ?public static byte[] hexStringToByte(String hex) { ?int len = (hex.length() / 2); ?byte[] result = new byte[len]; ?char[] hexChars = hex.toCharArray(); ?for (int i = 0; i < len; i++) { ?int pos = i * 2; ?result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4 ?| HEX_NUMS_STR.indexOf(hexChars[pos + 1])); ?} ?return result; ?} ? ?/** ?* 将指定byte数组转换成16进制字符串 ?* @param b ?* @return ?*/ ?public static String byteToHexString(byte[] b) { ?StringBuffer hexString = new StringBuffer(); ?for (int i = 0; i < b.length; i++) { ?String hex = Integer.toHexString(b[i] & 0xFF); ?if (hex.length() == 1) { ?hex = '0' + hex; ?} ?hexString.append(hex.toUpperCase()); ?} ?return hexString.toString(); ?} ? ?/** ?* 验证口令是否合法 ?* @param password ?* @param passwordInDb ?* @return ?* @throws NoSuchAlgorithmException ?* @throws UnsupportedEncodingException ?*/ ?public static boolean validPassword(String password, String passwordInDb) ?throws NoSuchAlgorithmException, UnsupportedEncodingException { ?//将16进制字符串格式口令转换成字节数组 ?byte[] pwdInDb = hexStringToByte(passwordInDb); ?//声明盐变量 ?byte[] salt = new byte[SALT_LENGTH]; ?//将盐从数据库中保存的口令字节数组中提取出来 ?System.arraycopy(pwdInDb, 0, salt, 0, SALT_LENGTH); ?//创建消息摘要对象 ?MessageDigest md = MessageDigest.getInstance("MD5"); ?//将盐数据传入消息摘要对象 ?md.update(salt); ?//将口令的数据传给消息摘要对象 ?md.update(password.getBytes("UTF-8")); ?//生成输入口令的消息摘要 ?byte[] digest = md.digest(); ?//声明一个保存数据库中口令消息摘要的变量 ?byte[] digestInDb = new byte[pwdInDb.length - SALT_LENGTH]; ?//取得数据库中口令的消息摘要 ?System.arraycopy(pwdInDb, SALT_LENGTH, digestInDb, 0, digestInDb.length); ?//比较根据输入口令生成的消息摘要和数据库中消息摘要是否相同 ?if (Arrays.equals(digest, digestInDb)) { ?//口令正确返回口令匹配消息 ?return true; ?} else { ?//口令不正确返回口令不匹配消息 ?return false; ?} ?} ?/** ?* 获得加密后的16进制形式口令 ?* @param password ?* @return ?* @throws NoSuchAlgorithmException ?* @throws UnsupportedEncodingException ?*/ ?public static String getEncryptedPwd(String password) ?throws NoSuchAlgorithmException, UnsupportedEncodingException { ?//声明加密后的口令数组变量 ?byte[] pwd = null; ?//随机数生成器 ?SecureRandom random = new SecureRandom(); ?//声明盐数组变量 ?byte[] salt = new byte[SALT_LENGTH]; ?//将随机数放入盐变量中 ?random.nextBytes(salt); ?//声明消息摘要对象 ?MessageDigest md = null; ?//创建消息摘要 ?md = MessageDigest.getInstance("MD5"); ?//将盐数据传入消息摘要对象 ?md.update(salt); ?//将口令的数据传给消息摘要对象 ?md.update(password.getBytes("UTF-8")); ?//获得消息摘要的字节数组 ?byte[] digest = md.digest(); ?//因为要在口令的字节数组中存放盐,所以加上盐的字节长度 ?pwd = new byte[digest.length + SALT_LENGTH]; ?//将盐的字节拷贝到生成的加密口令字节数组的前12个字节,以便在验证口令时取出盐 ?System.arraycopy(salt, 0, pwd, 0, SALT_LENGTH); ?//将消息摘要拷贝到加密口令字节数组从第13个字节开始的字节 ?System.arraycopy(digest, 0, pwd, SALT_LENGTH, digest.length); ?//将字节数组格式加密后的口令转化为16进制字符串格式的口令 ?return byteToHexString(pwd); ?} } 测试类——Client,代码如下: package com.zyg.security.md5; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; public class Client { ?private static Map users = new HashMap(); ?public static void main(String[] args){ ?String userName = "zyg"; ?String password = "123"; ?registerUser(userName,password); ?userName = "changong"; ?password = "456"; ?registerUser(userName,password); ?String loginUserId = "zyg"; ?String pwd = "1232"; ?try { ?if(loginValid(loginUserId,pwd)){ ?System.out.println("欢迎登陆!!!"); ?}else{ ?System.out.println("口令错误,请重新输入!!!"); ?} ?} catch (NoSuchAlgorithmException e) { ?// TODO Auto-generated catch block ?e.printStackTrace(); ?} catch (UnsupportedEncodingException e) { ?// TODO Auto-generated catch block ?e.printStackTrace(); ?} ?} ?/** ?* 注册用户 ?* ?* @param userName ?* @param password ?*/ ?public static void registerUser(String userName,String password){ ?String encryptedPwd = null; ?try { ?encryptedPwd = MyMD5Util.getEncryptedPwd(password); ?users.put(userName, encryptedPwd); ?} catch (NoSuchAlgorithmException e) { ?// TODO Auto-generated catch block ?e.printStackTrace(); ?} catch (UnsupportedEncodingException e) { ?// TODO Auto-generated catch block ?e.printStackTrace(); ?} ?} ?/** ?* 验证登陆 ?* ?* @param userName ?* @param password ?* @return ?* @throws UnsupportedEncodingException ?* @throws NoSuchAlgorithmException ?*/ ?public static boolean loginValid(String userName,String password) ?throws NoSuchAlgorithmException, UnsupportedEncodingException{ ?String pwdInDb = (String)users.get(userName); ?if(null!=pwdInDb){ // 该用户存在 ?return MyMD5Util.validPassword(password, pwdInDb); ?}else{ ?System.out.println("不存在该用户!!!"); ?return false; ?} ?} } |
|
PHP知识库 最新文章 |
Laravel 下实现 Google 2fa 验证 |
UUCTF WP |
DASCTF10月 web |
XAMPP任意命令执行提升权限漏洞(CVE-2020- |
[GYCTF2020]Easyphp |
iwebsec靶场 代码执行关卡通关笔记 |
多个线程同步执行,多个线程依次执行,多个 |
php 没事记录下常用方法 (TP5.1) |
php之jwt |
2021-09-18 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 23:38:42- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |