Java常见加密使用和分析

最近项目里碰到很多加解密的场景,使用多种加密的方式,大概整理了一下,一共有一下几种

加密方式 安全性 是否可逆
1 MD5 不可逆
2 AES 可逆
3 RSA 可逆
4 Base64 可逆

1.MD5加密

MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法)

MD5的一般在项目中的使用场景是密码加密,在校验密码时直接比较加密后的密文,对于这种不需要解密和展示的字段我们可以直接采用MD5的方式进行加密。MD5的本质就是将数据进行hash取得数据摘要,在一定程度上来说,MD5是无法被破解的。当然也可以通过撞库的方式来进行尝试破解,这个投入成本也是非常大的。为了避免撞库的命中率,还可以对MD5进行加盐。投入不同的随机字符串与数据进行拼接,亦或者在hash完的数据进行&运算。降低MD5撞库破解的威胁性。


Java中的使用MD5

public class MD5Util {//默认盐public static String LOCAL_SALT = "23543dfggeelysdafaqj23ou89ZXcj@#$@#$#@KJdjklj;D../dSF.,";//md5加密类private static MessageDigest md5;static {try {//获取md5实例md5 = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}/*** MD5加密* @param data* @return*/public static String encrypt(String data){//md5加密return byteArrayToHexString(md5.digest(data.getBytes()));}/*** MD5加盐加密* @param data* @param salt* @return*/public static String encrypt(String data,String salt){//加盐data +=salt;//md5加密return byteArrayToHexString(md5.digest(data.getBytes()));}//这里主要是遍历8个byte,转化为16位进制的字符,即0-Fprivate static String byteArrayToHexString(byte[] b) {StringBuffer resultSb = new StringBuffer();for (int i = 0; i < b.length; i++) {resultSb.append(byteToHexString(b[i]));}return resultSb.toString();}//这里是针对单个byte,256的byte通过16拆分为d1和d2private static String byteToHexString(byte b) {int n = b;if(n < 0) {n += 256;}int d1 = n / 16;int d2 = n % 16;return hexDigits[d1] + hexDigits[d2];}private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
}

java中获取到MessageDigest的md5实例后就可以完成MD5加密。

2.AES加密

高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。也就是我们常说的对称密钥加密,加密和解密用相同的密钥。

加密原理:轮密钥加实际是一种Vernam密码形式,其本身不难被破解。另外三个阶段一起提供了混淆、扩散和非线性功能。这三个阶段没有涉及密钥,就它们自身而言,并未提供算法的安全性。然而,该算法经历一个分组的XOR加密(轮密钥加),再对该分组混淆扩散(其他三个阶段),再接着又是XOR加密,如此交替进行,这种方式非常有效非常安全。

可逆原理:每个阶段均可逆。对字节代替、行移位和列混淆,在解密算法中用它们相对应的逆函数。轮密钥加的逆就是用同样的轮密钥和分组相异或,其原理就是A⊕B⊕B = A。和大多数分组密码一样,AES解密算法按逆序利用扩展密钥,然而其解密算法和加密算法并不一样,这是由AES的特定结构决定的。图5.3中加密和解密流程在纵向上是相反的,在每个水平点上,state数组在加密和解密函数中都是一样的。

AES加密的使用场景一般是在敏感信息在数据传输过程,微信小程序使用的AES加密传输数据。因为AES加解使用的是同一个密钥,AES可逆,如果密钥泄露也就意味着数据可以被解密。数据在频繁传输过程中,可能需要动态变更密钥来保证数据传输的安全性。


Java中AES加密

/*** AES对称密钥加解密*/
public class AESUtil {/*** 生成AES密钥* @return* @throws NoSuchAlgorithmException*/public static String generateKey() throws NoSuchAlgorithmException {KeyGenerator keyGenerator = KeyGenerator.getInstance("RSA");//初始化生成器keyGenerator.init(1024, new SecureRandom());//生成AES密钥SecretKey secretKey = keyGenerator.generateKey();byte[] keyByte = secretKey.getEncoded();return HexBin.encode(keyByte);}/*** 生成AES密钥* @param keySize 密钥最大长度* @return* @throws NoSuchAlgorithmException*/public static String generateKey(Integer keySize) throws NoSuchAlgorithmException {KeyGenerator keyGenerator = KeyGenerator.getInstance("RSA");//初始化生成器keyGenerator.init(keySize, new SecureRandom());//生成AES密钥SecretKey secretKey = keyGenerator.generateKey();byte[] keyByte = secretKey.getEncoded();return HexBin.encode(keyByte);}/*** AES加密* @param str* @param secreKey* @return* @throws Exception*/public static String encrypt( String str, String secreKey ) throws Exception{//密钥Key key  = new SecretKeySpec(HexBin.decode(secreKey),"AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//初始化加密cipher.init(Cipher.ENCRYPT_MODE, key);byte[] result = cipher.doFinal(str.getBytes());return HexBin.encode(result);}/*** AES解密* @param str* @param secreKey* @return* @throws Exception*/public static String decrypt(String str,String secreKey)  throws Exception{Key key  = new SecretKeySpec(HexBin.decode(secreKey),"AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//初始化解密cipher.init(Cipher.DECRYPT_MODE, key);byte[] result = cipher.doFinal(str.getBytes());return new String(result);}
}

java中的AES的加密完全依赖 Cipher类。RSA加解密使用也是这个类。

3.RSA加密

RSA是一种非对称加密算法。现在,很多登陆表单的密码的都采用RSA加密,例如京东中的登陆使用公钥对密码进行加密。

RSA这个加密算法就是经常听到非对称密钥加密,顾名思义,RSA加解密使用的不是同一个密钥,RSA中存在两个密钥,一个是公钥,一个是私钥,公钥暴露给数据发送端,私钥在数据接收端保留,数据发送端在数据传输前使用公钥加密数据,数据接受端在接收到数据时使用私钥解密,拿到真实数据。来保证数据传输的安全性。
RSA主要使用大整数分解这个数学难题进行设计,巧妙地利用了数论的概念,如今,只有短的 RSA 密钥才有可能被强力方式解破。长度足够长的密钥是安全系数时很高的。


Java中RSA加密

/*** RSA加解密工具类* @author machenike*/
public class RASUtil {/*** 密钥对存储场所*/private static KeyStore keyStore = new LocalKeyStore();/*** 当前线程持有的公钥*/private static ThreadLocal<String> currentPublicKey = new ThreadLocal<>();/*** 生成RSA密钥对* @return* @throws NoSuchAlgorithmException*/public static String[] generateKeyPair(){// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象KeyPairGenerator keyPairGen = null;try {keyPairGen = KeyPairGenerator.getInstance("RSA");} catch (NoSuchAlgorithmException e) {e.printStackTrace();e.printStackTrace();return null;}// 初始化密钥对生成器,密钥大小为96-1024位keyPairGen.initialize(1024,new SecureRandom());// 生成一个密钥对,保存在keyPair中KeyPair keyPair = keyPairGen.generateKeyPair();// 得到私钥RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();// 得到公钥RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));// 得到私钥字符串String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));// 将公钥和私钥保存到String数组String[] result = new String[2];result[0] = publicKeyString;result[1] = privateKeyString;return result;}/*** 生成RSA密钥对* @param keySize 密钥最大长度* @return* @throws NoSuchAlgorithmException*/public static String[] generateKeyPair(Integer keySize){// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象KeyPairGenerator keyPairGen = null;try {keyPairGen = KeyPairGenerator.getInstance("RSA");} catch (NoSuchAlgorithmException e) {e.printStackTrace();return null;}// 初始化密钥对生成器,密钥大小为96-1024位keyPairGen.initialize(keySize,new SecureRandom());// 生成一个密钥对,保存在keyPair中KeyPair keyPair = keyPairGen.generateKeyPair();/* 得到私钥 */RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();// 得到公钥RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));// 得到私钥字符串String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));// 将公钥和私钥保存到String数组String[] result = new String[2];result[0] = publicKeyString;result[1] = privateKeyString;return result;}/*** RSA公钥加密** @param str*            加密字符串* @param publicKey*            公钥* @return 密文* @throws Exception*             加密过程中的异常信息*/public static String encrypt( String str, String publicKey ) throws Exception{//base64编码的公钥byte[] decoded = Base64.decodeBase64(publicKey);RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));//RSA加密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, pubKey);String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));return outStr;}/*** 使用私钥进行RSA解密** @param str*            加密字符串* @param privateKey*            私钥* @return 铭文* @throws Exception*             解密过程中的异常信息*/public static String decrypt(String str, String privateKey) throws Exception{//64位解码加密后的字符串byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));//base64编码的私钥byte[] decoded = Base64.decodeBase64(privateKey);RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));//RSA解密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, priKey);String outStr = new String(cipher.doFinal(inputByte));return outStr;}/*** 通过当前的线程的公钥进行RSA私钥解密** @param str*            加密字符串*            私钥* @return 铭文* @throws Exception*             解密过程中的异常信息*/public static String decrypt(String str) throws Exception{//64位解码加密后的字符串byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));//base64编码的私钥byte[] decoded = Base64.decodeBase64(keyStore.getPrivateKey(currentPublicKey.get()));RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));//RSA解密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, priKey);String outStr = new String(cipher.doFinal(inputByte));return outStr;}/*** 获取当前线程得公共键* @param currentPublicKey*/public static void setCurrentPublicKey(String currentPublicKey){RASUtil.currentPublicKey.set(currentPublicKey);}/*** 设定存储密钥的实现* @param keyStore*/public static void setKeyStore(KeyStroke keyStore){keyStore = keyStore;}
}

使用KeyPairGenerator生成密钥对,同时服务端会将公钥返回到客户端,客户端是RSA进行加密,而私钥保存在系统内部,不对外暴露,收到数据时使用cipher进行解密。保证数据传输的安全性,就算数据被抓包抓到,只要数据没有经过后台,那么数据就是无法解密。

4.Base64加密

Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。采用Base64编码具有不可读性,需要解码后才能阅读

其实base64不算是一种加密方式,只能说是一种特定的编码方式,目的是为了方便数据传输。比如图片可以转成base64字符串进行传输,接收完数据后,在进行base64解码就可把图片还原出来。


Java中Base64

/*** Base64解码编码工具类*/
public class Base64Util {//解码器private static final Base64.Decoder decoder = Base64.getDecoder();//编码器private static final Base64.Encoder encoder = Base64.getEncoder();/*** Base64编码* @param data* @return*/public static String encode(String data){return encoder.encodeToString(data.getBytes());}/*** Base64解码* @param data* @return*/public static String decode(String data){return new String(decoder.decode(data.getBytes()));}
}

上面所有的常用方法我都已经整理集成到我的安全包里。
https://github.com/DavidLei08/s-encrypt.git

Java常见加密使用和分析相关推荐

  1. Java常见内存溢出异常分析

    Java虚拟机规范规定JVM的内存分为了好几块,比如堆,栈,程序计数器,方法区等,而Hotspot jvm的实现中,将堆内存分为了三部分,新生代,老年代,持久带,其中持久带实现了规范中规定的方法区,而 ...

  2. 逆向爬虫35 常见加密的python实现

    逆向爬虫35 常见加密的python实现 目的:将App逆向中常见的算法用python实现,方便以后的使用 Java常见加密 隐藏字符串 字符串是以字节编码数组的形式存储或网络传输的,因此可以通过指定 ...

  3. Java常见的加密解密

    Java常见的加密解密 不可逆加密 介绍 应用场景 一致性验证 MD5 可以为文件传输场景中,提供文件的一致性验证. 例如,文件服务器预先提供一个 MD5 校验值,用户下载完文件以后,用 MD5 算法 ...

  4. Java常见应用——Json,二维码生成,加密解密应用

    Java常见应用--Json,二维码生成,加密解密应用 一.JSON 1.下载json架包,json官网:json.org 2.将Map/JavaBean/String转化成json对象,只需要使用J ...

  5. Java常见异常类型及原因分析

    Java常见异常类型及原因分析 0x1 NullPointerException异常 顾名思义,NullPointerException 是空指针异常.但是在 Java 中没有指针,怎么会有 空指针异 ...

  6. Java DES 加密解密

    1.加密的相关概念 1.明文:被隐蔽的消息称作明文(plaintext) 2.密文:隐蔽后的消息称作密文(ciphertext) 3.加密:将明文变换成密文的过程称作加密(encryption) 4. ...

  7. JAVA各种加密与解密方式

    之前有兴趣研究了一下java的加密与解密的方法,发现市面上有好多种加密解密方式,在这里整理了一下. 目录 1.BASE64加密/解密 2.MD5(Message Digest Algorithm)加密 ...

  8. java 密码加密 盐_有效提高java编程安全性的12条黄金法则

    安全性是软件开发中最复杂,最广泛和最重要的考量之一.Java是具有许多内置安全性功能的开发平台,java在长期的发展过程中,已经经过了很多高强度的安全测试,并经常更新安全漏洞.并且Java生态系统还包 ...

  9. java常见对象_Java/10_Java常见对象.md at master · DuHouAn/Java · GitHub

    Java常见对象 Arrays Arrays:针对数组进行操作的工具类. Arrays的常用成员方法: public static String toString(int[] a) //把数组转成字符 ...

最新文章

  1. AI服务器的设计与实现
  2. java实现二进制转十六进制
  3. python 修改模板对象的属性_django小技巧之html模板中调用对象属性或对象的方法...
  4. HTTP系列之:HTTP缓存
  5. 经典的K-means聚类算法
  6. ubuntu不锁屏设置
  7. MySQL数据查询SELECT大全
  8. eclipse console 输出数据量大时不完整问题
  9. FTP服务器是什么【摘自IT百科】
  10. hihocoder 1224 赛车
  11. 服务器主板主要组成部分(个人笔记,请勿参考)
  12. 支付宝将推出免费WiFi
  13. java实现简单的LUR算法
  14. GitChat · 架构 | 如何从零开始搭建高性能直播平台?
  15. SaltStack常用模块之file
  16. 河北大学计算机学院赵润,2010年河北省高招录取名单(7月20日)41
  17. CDH6.1.0环境搭建 完成后 登录admin账户失败
  18. termux-x11教程
  19. pyqt5实现桌面便签及提醒——逐步更新
  20. 二手车车辆购置税税率及过户费的计算

热门文章

  1. 含有DBCO和马来酰亚胺基团Mal-PEG2-DBCO,2698339-31-8,DBCO-PEG2-Maleimide
  2. 详解在QT中写控制台程序 实例
  3. Holistic Multi-modal Memory Network for Movie Question Answering心得体会
  4. 企业标准化产线建设_中铁十四局集团第一工程发展有限公司 公司新闻 强化示范引领,不断推进建家建线规范化、标准化、细致化————一公司建家建线标准化观摩会在青岛新机场项目部召开...
  5. cocoapod 设置
  6. Arangodb最短路径查询语法
  7. CRMEB二次开发新增用户评论关键词过滤、后台审核通过后前端才显示评论信息
  8. http://www.mianwww.com/html/category/it-interview/spring/
  9. 高级OS(八) - Linux内存映射
  10. 阿里云mysql 分库分表_阿里云rds mysql分库分表