java加密算法入门(一)-算法概念及单向加密
说起加密,我的第一印象就是电视剧各种密码本破解解密的场景,这两天在看加密相关的东西,做下笔记以便以后查看,也提供给大家个参考。
本文是java加密的第一篇,主要讲述下消息编码Base64以及简单的消息摘要算法MD5,SHA,MAC等,如果有不对的地方还望大家指正。
1、算法概念简述
1.1、加密算法分类
消息编码:Base64 消息摘要:MD类,SHA类,MAC 对称加密:DES,3DES,AES 非对称加密:RSA,DH密钥交换 数字签名:RSA signature,DSA signature
1.2、算法的主要流程
明文-->加密算法--> 密文 --> 解密算法 --> 明文
1.3、常用的jar包
1、jdk自身提供的加密类
2、其他提供加密的第三方jar包
Apache Commons Codec(简称CC),
Bouncy Castle(BC)
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.57</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency>
2、消息摘要算法
消息摘要算法,可谓是非可逆加密,就是不可解密的加密方法。当然现在网上也有大神将一些算法破解解密的例子,这只是特例。
2.1、使用BASE64编码格式
为什么是使用base64编码呢,因为严格地说,Base64属于编码格式,而非加密算法。我在网上有看到一个base64产生的背景,看完这个相信大家就会理解我说的这句话了。
Base64算法最早主要是解决电子邮件的传输问题,由于当时的网关有个问题就是可能会使非ASCII码字符的二进制位做调整,导致用户收取的邮件变成乱码,所以就出现了Base64算法。
什么是base64算法?
按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。
常见于邮件、http加密,截取http信息,你就会发现登录操作的用户名、密码字段通过BASE64加密的。
算法流程:
明文-->Base64加密--> 密文 --> Base64解密 --> 明文
代码实现:
base64目前主要是通过jdk自带的类实现,也有BC和CC等第三方的解决方案,根据我的了解,BC是对jdk的补充,CC主要是对jdk操作的简化,大家可以在后面的代码中看到的。
package checkcode; import org.apache.commons.codec.binary.Base64; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; /** * {@link http://www.cnblogs.com/allanzhang/} * @author 小卖铺的老爷爷 * */ public class Base64Test { public static final String src = "laoyeye base64"; public static void main(String[] args) { jdkBase64(); commonsCodesBase64(); bouncyCastleBase64(); } // 用jdk实现 public static void jdkBase64() { try { BASE64Encoder encoder = new BASE64Encoder(); String encode = encoder.encode(src.getBytes()); System.out.println("encode:" + encode); BASE64Decoder decoder = new BASE64Decoder(); System.out.println("decode:" + new String(decoder.decodeBuffer(encode))); } catch (Exception e) { e.printStackTrace(); } } // 用Apache的common codes实现 public static void commonsCodesBase64() { byte[] encodeBytes = Base64.encodeBase64(src.getBytes()); System.out.println("common codes encode:" + new String(encodeBytes)); byte[] dencodeBytes = Base64.decodeBase64(encodeBytes); System.out.println("common codes decode:" + new String(dencodeBytes)); } // 用bouncy castle实现 public static void bouncyCastleBase64() { byte[] encodeBytes = org.bouncycastle.util.encoders.Base64.encode(src.getBytes()); System.out.println("bouncy castle encode:" + new String(encodeBytes)); byte[] dencodeBytes = org.bouncycastle.util.encoders.Base64.decode(encodeBytes); System.out.println("bouncy castle decode:" + new String(dencodeBytes)); } }
效果图:
注:BASE加密后产生的字节位数是8的倍数,如果不够位数以=符号填充。
2.2 MD(Message Digest algorithm,信息摘要算法)
MD算法目前使用最多的大概就是MD5了吧,MD5的全称是Message-Digest Algorithm 5(信息-摘要算法),在90年代初由MIT Laboratory for Computer Science和RSA Data Security Inc的Ronald L. Rivest开发出来,经MD2和MD4等发展而来。目前jdk提供了MD2和MD5的实现,对于MD4我们需要借助BC来实现。现在MD广泛用于加密和解密技术,常用于文件校验。不管文件多大,经过MD后都能生成唯一的MD值。好比现在的ISO校验,都是MD校验。怎么用?当然是把ISO经过MD后产生MD的值。一般下载linux-ISO的朋友都见过下载链接旁边放着MD的串。就是用来验证文件是否一致的。
加密流程:
明文-->MD加密--> 密文--> 接收者
明文-->接收者--> MD加密--> 密文--> 比较验证
代码实现:
package checkcode; import java.security.MessageDigest; import java.security.Security; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.crypto.digests.MD4Digest; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.jce.provider.BouncyCastleProvider; /** * {@link http://www.cnblogs.com/allanzhang/} * @author 小卖铺的老爷爷 * */ public class MD5Test { public static final String src = "laoyeye md5"; public static void main(String[] args) { jdkMD5(); jdkMD2(); bcMD4(); bcMD5(); bc2jdkMD4(); ccMD5(); ccMD2(); } // 用jdk实现:MD5 public static void jdkMD5() { try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] md5Bytes = md.digest(src.getBytes()); System.out.println("JDK MD5:" + Hex.encodeHexString(md5Bytes)); } catch (Exception e) { e.printStackTrace(); } } // 用jdk实现:MD2 public static void jdkMD2() { try { MessageDigest md = MessageDigest.getInstance("MD2"); byte[] md2Bytes = md.digest(src.getBytes()); System.out.println("JDK MD2:" + Hex.encodeHexString(md2Bytes)); } catch (Exception e) { e.printStackTrace(); } } // 用bouncy castle实现:MD5 public static void bcMD5() { MD5Digest digest = new MD5Digest(); digest.update(src.getBytes(),0,src.getBytes().length); byte[] md5Bytes = new byte[digest.getDigestSize()]; digest.doFinal(md5Bytes, 0); System.out.println("bouncy castle MD5:" + Hex.encodeHexString(md5Bytes)); } // 用bouncy castle实现:MD4 public static void bcMD4() { MD4Digest digest = new MD4Digest(); digest.update(src.getBytes(),0,src.getBytes().length); byte[] md4Bytes = new byte[digest.getDigestSize()]; digest.doFinal(md4Bytes, 0); System.out.println("bouncy castle MD4:" + Hex.encodeHexString(md4Bytes)); } // 用bouncy castle与jdk结合实现:MD4 public static void bc2jdkMD4() { try { Security.addProvider(new BouncyCastleProvider()); MessageDigest md = MessageDigest.getInstance("MD4"); byte[] md4Bytes = md.digest(src.getBytes()); System.out.println("bc and JDK MD4:" + Hex.encodeHexString(md4Bytes)); } catch (Exception e) { e.printStackTrace(); } } // 用common codes实现实现:MD5 public static void ccMD5() { System.out.println("common codes MD5:" + DigestUtils.md5Hex(src.getBytes())); } // 用common codes实现实现:MD2 public static void ccMD2() { System.out.println("common codes MD2:" + DigestUtils.md2Hex(src.getBytes())); } }
2.3 SHA(Secure Hash Algorithm,安全散列算法)
SHA现在主要有SHA1和SHA2两大类,SH2又分好多种,大家可以网上看下。SHA,被广泛地应用于电子商务等信息安全领域。虽然,SHA与MD5通过碰撞法都被破解了, 但是SHA仍然是公认的安全加密算法,较之MD5更为安全。
加密流程:
明文-->SHA加密--> 密文--> 接收者
明文-->接收者--> SHA加密--> 密文--> 比较验证
代码实现:
package checkcode; import java.math.BigInteger; import java.security.MessageDigest; import java.security.Security; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.digests.SHA224Digest; import org.bouncycastle.jce.provider.BouncyCastleProvider; /** * {@link http://www.cnblogs.com/allanzhang/} * @author 小卖铺的老爷爷 * */ public class SHATest { public static final String src = "laoyeye sha"; public static void main(String[] args) { jdkSHA1(); bcSHA1(); bcSHA224(); bcSHA224b(); generateSha256(); ccSHA1(); } // 用jdk实现:SHA1 public static void jdkSHA1() { try { MessageDigest md = MessageDigest.getInstance("SHA"); md.update(src.getBytes()); System.out.println("jdk sha-1:" + Hex.encodeHexString(md.digest())); } catch (Exception e) { e.printStackTrace(); } } // 用bouncy castle实现:SHA1 public static void bcSHA1() { Digest digest = new SHA1Digest(); digest.update(src.getBytes(), 0, src.getBytes().length ); byte[] sha1Bytes = new byte[digest.getDigestSize()]; digest.doFinal(sha1Bytes, 0); System.out.println("bc sha-1:" + org.bouncycastle.util.encoders.Hex.toHexString(sha1Bytes)); } // 用bouncy castle实现:SHA224 public static void bcSHA224() { Digest digest = new SHA224Digest(); digest.update(src.getBytes(), 0, src.getBytes().length ); byte[] sha224Bytes = new byte[digest.getDigestSize()]; digest.doFinal(sha224Bytes, 0); System.out.println("bc sha-224:" + org.bouncycastle.util.encoders.Hex.toHexString(sha224Bytes)); } // 用bouncy castle与jdk结合实现:SHA224 public static void bcSHA224b() { try { Security.addProvider(new BouncyCastleProvider()); MessageDigest md = MessageDigest.getInstance("SHA224"); md.update(src.getBytes()); System.out.println("bc and JDK sha-224:" + Hex.encodeHexString(md.digest())); } catch (Exception e) { e.printStackTrace(); } } public static void generateSha256() { MessageDigest md = null; try { md = MessageDigest.getInstance("SHA-256"); md.update(src.getBytes("UTF-8")); // Change this to "UTF-16" if needed } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } byte[] digest = md.digest(); BigInteger bigInt = new BigInteger(1, digest); System.out.println("Sha256 hash: " + bigInt.toString(16)); } // 用common codes实现实现:SHA1 public static void ccSHA1() { System.out.println("common codes SHA1 - 1 :" + DigestUtils.sha1Hex(src.getBytes())); System.out.println("common codes SHA1 - 2 :" + DigestUtils.sha1Hex(src)); } }
效果图:
SHA-与MD的比较
因为二者均由MD导出,SHA-和MD彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
对强行攻击的安全性:最显著和最重要的区别是SHA-摘要比MD摘要长。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD是^数量级的操作,而对SHA-则是^数量级的操作。这样,SHA-对强行攻击有更大的强度。
对密码分析的安全性:由于MD的设计,易受密码分析的攻击,SHA-显得不易受这样的攻击。
速度:在相同的硬件上,SHA-的运行速度比MD慢。
2.4 HMAC(Hash Message Authentication Code,散列消息鉴别码)
基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,用这个 标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。
加密流程:
构建秘钥-->发送秘钥--> 接收者
明文-->HMAC算法+秘钥加密--> 密文--> 接收者
明文-->接收者--> HMAC算法+秘钥加密--> 密文--> 比较验证
代码实现:
package checkcode; import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.crypto.params.KeyParameter; /** * {@link http://www.cnblogs.com/allanzhang/} * @author 小卖铺的老爷爷 * */ public class HMACTest { public static final String src = "laoyeye hmac"; public static void main(String[] args) { jdkHmacMD5(); bcHmacMD5(); } // 用jdk实现: public static void jdkHmacMD5() { try { // 初始化KeyGenerator KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5"); // 产生密钥 SecretKey secretKey = keyGenerator.generateKey(); //1、 获取密钥 // byte[] key = secretKey.getEncoded(); //2、使用固定秘钥 byte[] key = Hex.decodeHex(new char[]{'1','2','3','4','5','6','7','8','9','a','b','c','d','e' }); // 还原密钥 SecretKey restoreSecretKey = new SecretKeySpec(key, "HmacMD5"); // 实例化MAC Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm()); // 初始化MAC mac.init(restoreSecretKey); // 执行摘要 byte[] hmacMD5Bytes = mac.doFinal(src.getBytes()); System.out.println("jdk hmacMD5:" + Hex.encodeHexString(hmacMD5Bytes)); } catch (Exception e) { e.printStackTrace(); } } // 用bouncy castle实现: public static void bcHmacMD5() { HMac hmac = new HMac(new MD5Digest()); // 必须是16进制的字符,长度必须是2的倍数 hmac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex.decode("123456789abcde"))); hmac.update(src.getBytes(), 0, src.getBytes().length); // 执行摘要 byte[] hmacMD5Bytes = new byte[hmac.getMacSize()]; hmac.doFinal(hmacMD5Bytes, 0); System.out.println("bc hmacMD5:" + org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5Bytes)); } }
效果图:
总结:
BASE64的加密解密是双向的,可以得出明文和密文。
MD5、SHA以及HMAC是单向加密,任何数据加密后只会产生唯一的一个加密串,通常用来校验数据在传输过程中是否被修改。其中HMAC算法有一个密钥,增强了数据传输过程中的安全性,强化了算法外的不可控因素。
单向加密的用途主要是为了校验数据在传输过程中是否被修改。
java加密算法入门(一)-算法概念及单向加密的更多相关文章
- java加密算法入门(二)-对称加密详解
1.简单介绍 什么是对称加密算法? 对称加密算法即,加密和解密使用相同密钥的算法. 优缺点: 优点:算法公开.计算量小.加密速度快.加密效率高. 缺点: (1)交易双方都使用同样钥匙,安全性得不到保证 ...
- java加密算法入门(三)-非对称加密详解
1.简单介绍 这几天一直在看非对称的加密,相比之前的两篇内容,这次看了两倍多的时间还云里雾里的,所以这篇文章相对之前的两篇,概念性的东西多了些,另外是代码的每一步我都做了介绍,方便自己以后翻阅,也方便 ...
- 基本的java加密算法MD5等等
简单的java加密算法有: BASE64 严格地说,属于编码格式,而非加密算法 MD5 (Message Digest algorithm 5,信息摘要算法) SH ...
- C功底挑战Java菜鸟入门概念干货(一)
一.认识Java 1.Java 程序比较特殊,它必须先经过编译,然后再利用解释的方式来运行. 2.Byte-codes 最大的好处是——可越平台运行,可让“一次编写,处处运行”成为可能. 3.使用 ...
- C功底挑战Java菜鸟入门概念干货(二)
(接上篇博文:C功底挑战Java菜鸟入门概念干货(一)) 一.Java面向对象程序设计-类的基本形式 1.“类”是把事物的数据与相关的功能封装在一起,形成的一种特殊结构,用以表达对真实世界的一种抽象概 ...
- Java 算法 概念汇总
编程面试的10大算法概念汇总 以下是在编程面试中排名前10的算法相关的概念,我会通过一些简单的例子来阐述这些概念.由于完全掌握这些概念需要更多的努力,因此这份列表只是作为一个介绍.本文将从Java ...
- JAVA入门(1.JAVA平台应用 2.核心概念:JVM,JDK,JRE 3.搭建JAVA开发环境 4.学习JAVA的原则)
主要内容: 1.JAVA平台应用 2.核心概念:JVM,JDK,JRE 3.搭建JAVA开发环境 4.学习JAVA的原则 JAVA的平台应用 JAVA的平台应用分为3个部分: 一.JAVA SE,主要 ...
- ECC加密算法入门介绍 --- 看雪
标 题:ECC加密算法入门介绍 作 者:zmworm 时 间:2003/05/04 08:32pm 链 接:http://bbs.pediy.com ECC加密算法入门介绍 作者 :ZMWorm[C ...
- [转]Java加密算法
如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algorit ...
随机推荐
- 关于mpu6050的几个很好的帖子
最近在研究6050,真是很磨人啊,这个小东西还挺复杂,一个读取程序竟然需要600多行. 这几天连查资料找到了几个很好的帖子,要是以后有人看到这篇帖子,可以避免误入歧途,也可以省去很多时间. 1.阿西莫 ...
- Linux 练习(1)
1) 新建用户natasha,uid为1000,gid为555,备注信息为"master" useradd -u 1000 -g 555 -c 'master' natasha2) ...
- 线段树区间更新操作及Lazy思想(详解)
此题题意很好懂: 给你N个数,Q个操作,操作有两种,‘Q a b ’是询问a~b这段数的和,‘C a b c’是把a~b这段数都加上c. 需要用到线段树的,update:成段增减,query:区间求 ...
- FTP中MLST概要解读---解决获取ftpFile为null的另外一种方式
零.引言 之前写FTP工具库,用的是ftp4j,他使用其他非常简单方便,但是在细节上提供的可选项比较少(当然也可能是我了解不够深刻) 最新的项目重写了FTP工具类,选择了apache net中的ftp ...
- nginx源码分析——configure脚本
源码:nginx 1.13.0-release 一.前言 在分析源码时,经常可以看到类似 #if (NGX_PCRE) .... #endif 这样的代码段,这样的设计可以在不改动源码的 ...
- Linux 零拷贝技术
简介 零拷贝(zero-copy)技术可以减少数据拷贝和共享总线操作的次数,消除通信数据在存储器之间不必要的中间拷贝过程,有效地提高通信效率,是设计高速接口通道.实现高速服务器和路由器的关键技术之一. ...
- java文件的读写操作
java文件的读写操作主要是对输入流和输出流的操作,由于流的分类很多,所以概念很容易模糊,基于此,对于流的读写操作做一个小结. 1.根据数据的流向来分: 输出流:是用来写数据的,是由程序(内存)--- ...
- 欲练JS,必先攻CSS——前端修行之路(码易直播)
以下是直播大概内容的文字版: 感谢大家今天来到直播间收听本期的码易直播.今天我讲的主题是css,具体聊一下我大概的css学习历史,分享一些干货,希望这次分享对大家有所启发和帮助. 个人的css历史: ...
- 转:Redis配置文件详解
配置与特性详解 1. 在redis中,合法的"尺寸单位",无大小写区分. # 1k => bytes # 1kb => bytes # 1m => bytes # ...
- m个苹果放入n个盘子问题
这个问题,看似是一个简单的排列组合问题,但是加上不同的限制条件,会演变成不同的问题,感觉很奇妙,就总结一下列举下来 问题一 问题描述:把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问有多 ...