一)关于加密算法

信息加密是现在几乎所有项目都需要用到的技术,身份认证、单点登陆、信息通讯、支付交易等场景中经常会需要用到加密算法,所谓加密算法,就是将原本的明文通过一系列算法操作变成密文。接下来就介绍一下目前比较常用的一些加密算法,本期不涉及算法底层,以应用介绍和代码展示为主。

如果只想了解原理,可跳过代码部分,代码可直接拿来使用。

(二)MD5算法

准确来讲,MD5不是一种加密算法,而是一种摘要算法,MD5能将明文输出为128bits的字符串,这个字符串是无法再被转换成明文的。网上一些MD5解密网站也只是保存了一些字符串对应的md5串,通过已经记录的md5串来找出原文。

我做过的几个项目中经常见到MD5用在加密上的场景。比如对密码的加密,生成一个密码后,使用MD5生成一个128位字符串保存在数据库中,用户输入密码后也先生成MD5串,再去数据库里比较。因此我们在找回密码时是无法得到原来的密码的,因为明文密码根本不会被保存。

public class MD5 {/*** 生成MD5* @param str* @return*/public String encode(String str) {byte[] result = null;try {MessageDigest md = MessageDigest.getInstance("MD5");md.update(str.getBytes("UTF-8"));result = md.digest();} catch (Exception e) {e.printStackTrace();return null;}return parseByte2HexStr(result);}/*** 将二进制转换成十六进制** @param buf* @return*/private String parseByte2HexStr(byte buf[]) {StringBuffer sb = new StringBuffer();for (int i = 0; i < buf.length; i++) {String hex = Integer.toHexString(buf[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}sb.append(hex.toUpperCase());}return sb.toString();}public static void main(String[] args) {MD5 md5=new MD5();String content = "测试test";System.out.println(md5.encode(content));}
}
复制代码

(三)SHA1算法

SHA1也是和MD5类似的信息摘要算法,但是它比MD5更加安全。

public class SHA1 {public String encode(String str) {try {MessageDigest md = MessageDigest.getInstance("SHA-1");md.update(str.getBytes("utf-8"));byte[] digest = md.digest();return byteToHexString(digest);} catch (Exception e) {e.printStackTrace();return null;}}public static String byteToHexString(byte[] bytes) {return String.valueOf(Hex.encodeHex(bytes));}public static void main(String[] args) {SHA1 sha1 = new SHA1();String content = "测试test";System.out.println(sha1.encode(content));}
}
复制代码

(四)AES算法

AES是很常见的对称加密算法,所谓对称加密,就是通过密钥加密后可以再通过密钥解密。我接触过的某个国企现在内部就是采用AES的方式实现集成登陆。第三方系统提供一个接收用户信息的接口,该国企将用户信息AES加密后通过这个接口传递给第三方系统,第三方系统自行实现登陆操作。这里需要注意的是密钥十分重要,如果密钥丢失,就有信息泄漏的风险。

public class AES {/*** 将传入的明文转换为密文* @param str* @param pwd* @return*/public String encode(String str,String pwd) {byte[] result = null;try {KeyGenerator kgen = KeyGenerator.getInstance("AES");SecureRandom random = SecureRandom.getInstance("SHA1PRNG");random.setSeed(pwd.getBytes());kgen.init(128, random);SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 创建密码器Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, key);byte[] byteContent = str.getBytes();result = cipher.doFinal(byteContent);} catch (Exception e) {return null;}return parseByte2HexStr(result);}/*** 将传入的密文转换为明文* @param str* @param pwd* @return*/public String decode(String str,String pwd) {byte[] result = null;byte[] content = parseHexStr2Byte(str);try {KeyGenerator kgen = KeyGenerator.getInstance("AES");SecureRandom random = SecureRandom.getInstance("SHA1PRNG");random.setSeed(pwd.getBytes());kgen.init(128, random);SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 创建密码器Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, key);result = cipher.doFinal(content);} catch (Exception e) {e.printStackTrace();return null;}return new String(result);}/*** 将二进制转换成十六进制** @param buf* @return*/private String parseByte2HexStr(byte buf[]) {StringBuffer sb = new StringBuffer();for (int i = 0; i < buf.length; i++) {String hex = Integer.toHexString(buf[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}sb.append(hex.toUpperCase());}return sb.toString();}/*** 将十六进制转换为二进制** @param hexStr* @return*/private byte[] parseHexStr2Byte(String hexStr) {if (hexStr.length() < 1) {return null;}byte[] result = new byte[hexStr.length() / 2];for (int i = 0; i < hexStr.length() / 2; i++) {int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);result[i] = (byte) (high * 16 + low);}return result;}public static void main(String[] args) {AES aes = new AES();String content = "测试加密";// AES的密钥长度最好是16位(不是必须)String pwd = "javayznbjavayznb";// 加密System.out.println("加密前:" + content);String encodeResultStr = aes.encode(content,pwd);System.out.println("加密后:" + encodeResultStr);// 解密String decodeResultStr = aes.decode(encodeResultStr,pwd);System.out.println("解密后:" + decodeResultStr);}}
复制代码

(五)DES

DES也是一种对称加密算法,但是在安全性、效率和灵活性上比AES略差,但是也能保证安全,DES也需要通过密钥进行加密,通过密钥进行解密,因此密钥很重要:

public class DES {/*** 将传入的明文转换为密文* @param str* @param pwd* @return*/public String encode(String str,String pwd) {byte[] result = null;try {DESKeySpec keySpec = new DESKeySpec(pwd.getBytes());SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");SecretKey key = keyFactory.generateSecret(keySpec);Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, key);byte[] byteContent = str.getBytes();result = cipher.doFinal(byteContent);} catch (Exception e) {e.printStackTrace();return null;}return parseByte2HexStr(result);}/*** 将传入的密文转换为明文* @param str* @param pwd* @return*/public String decode(String str,String pwd) {byte[] result = null;byte[] content = parseHexStr2Byte(str);try {DESKeySpec keySpec = new DESKeySpec(pwd.getBytes());SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");SecretKey key = keyFactory.generateSecret(keySpec);Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, key);result = cipher.doFinal(content);} catch (Exception e) {e.printStackTrace();return null;}return new String(result);}/*** 将二进制转换成十六进制** @param buf* @return*/private String parseByte2HexStr(byte buf[]) {StringBuffer sb = new StringBuffer();for (int i = 0; i < buf.length; i++) {String hex = Integer.toHexString(buf[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}sb.append(hex.toUpperCase());}return sb.toString();}/*** 将十六进制转换为二进制** @param hexStr* @return*/private byte[] parseHexStr2Byte(String hexStr) {if (hexStr.length() < 1) {return null;}byte[] result = new byte[hexStr.length() / 2];for (int i = 0; i < hexStr.length() / 2; i++) {int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);result[i] = (byte) (high * 16 + low);}return result;}public static void main(String[] args) {DES des = new DES();String content = "测试test";// DES的密钥长度必须是8位(小于8位则会报错,8位之后对加密结果不会产生影响)String pwd = "javayznb";// 加密System.out.println("加密前:" + content);String encodeResultStr = des.encode(content,pwd);System.out.println("加密后:" + encodeResultStr);//解密String decodeResultStr = des.decode(encodeResultStr,pwd);System.out.println("解密后:" + decodeResultStr);}
}
复制代码

(六)RSA

RSA是目前最具影响力的公钥加密算法,并且可以用于加密和验签。支付宝支付对接时用的加密方式就是RSA。在RSA中,存在一对密钥,分别称为公钥和私钥,通过私钥由个人保存,公钥可能多人持有

RSA的主要应用场景就是加密和验签,加密就不用说了,验签是指通过私钥对消息进行签名,使得消息无法篡改和伪造。

加密方式:B传加密数据给A

1、A生成公钥和私钥,私钥自己保留,公钥任何人可以获取。

2、B拿到公钥,将数据通过公钥加密

3、A收到密文,通过私钥解密。

验签方式:A传消息给B 1、A生成公钥和私钥,私钥自己保留,公钥任何人可以获取。

2、A使用私钥对消息加签,并将加签后的消息传给B。

3、B通过公钥验签,如果返回是true则说明消息是A发过来的且未被篡改。

public class TestRSA {/*** RSA最大加密明文大小*/private static final int MAX_ENCRYPT_BLOCK = 117;/*** RSA最大解密密文大小*/private static final int MAX_DECRYPT_BLOCK = 128;/*** 获取密钥对** @return 密钥对*/public static KeyPair getKeyPair() throws Exception {KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");generator.initialize(1024);return generator.generateKeyPair();}/*** 获取私钥** @param privateKey 私钥字符串* @return*/public static PrivateKey getPrivateKey(String privateKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);return keyFactory.generatePrivate(keySpec);}/*** 获取公钥** @param publicKey 公钥字符串* @return*/public static PublicKey getPublicKey(String publicKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);return keyFactory.generatePublic(keySpec);}/*** RSA加密** @param data 待加密数据* @param publicKey 公钥* @return*/public static String encrypt(String data, PublicKey publicKey) throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);int inputLen = data.getBytes().length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offset = 0;byte[] cache;int i = 0;// 对数据分段加密while (inputLen - offset > 0) {if (inputLen - offset > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);}out.write(cache, 0, cache.length);i++;offset = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();// 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串// 加密后的字符串return new String(Base64.encodeBase64String(encryptedData));}/*** RSA解密** @param data 待解密数据* @param privateKey 私钥* @return*/public static String decrypt(String data, PrivateKey privateKey) throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] dataBytes = Base64.decodeBase64(data);int inputLen = dataBytes.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offset = 0;byte[] cache;int i = 0;// 对数据分段解密while (inputLen - offset > 0) {if (inputLen - offset > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(dataBytes, offset, inputLen - offset);}out.write(cache, 0, cache.length);i++;offset = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();// 解密后的内容return new String(decryptedData, "UTF-8");}/*** 签名** @param data 待签名数据* @param privateKey 私钥* @return 签名*/public static String sign(String data, PrivateKey privateKey) throws Exception {byte[] keyBytes = privateKey.getEncoded();PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey key = keyFactory.generatePrivate(keySpec);Signature signature = Signature.getInstance("MD5withRSA");signature.initSign(key);signature.update(data.getBytes());return new String(Base64.encodeBase64(signature.sign()));}/*** 验签** @param srcData 原始字符串* @param publicKey 公钥* @param sign 签名* @return 是否验签通过*/public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {byte[] keyBytes = publicKey.getEncoded();X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey key = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance("MD5withRSA");signature.initVerify(key);signature.update(srcData.getBytes());return signature.verify(Base64.decodeBase64(sign.getBytes()));}public static void main(String[] args) {try {// 生成密钥对KeyPair keyPair = getKeyPair();String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));System.out.println("私钥:" + privateKey);System.out.println("公钥:" + publicKey);// RSA加密String data = "待加密的文字内容";String encryptData = encrypt(data, getPublicKey(publicKey));System.out.println("加密后内容:" + encryptData);// RSA解密String decryptData = decrypt(encryptData, getPrivateKey(privateKey));System.out.println("解密后内容:" + decryptData);// RSA签名String sign = sign(data, getPrivateKey(privateKey));System.out.println("加签后:"+sign);// RSA验签boolean result = verify(data, getPublicKey(publicKey), sign);System.out.print("验签结果:" + result);} catch (Exception e) {e.printStackTrace();System.out.print("加解密异常");}}
}
复制代码

(七)总结

关于加密这个问题不管是工作中还是面试中都会被提及,也必须要掌握。不要求加密的代码能手写,但是要知道每种加密算法是干什么的,是什么样的效果。

本文首发于java黑洞网,csdn同步更新

浅析五种最常用的Java加密算法,以后可以直接拿来用了相关推荐

  1. java经典密码算法,浅析五种最常用的Java加密算法,以后可以直接拿来用了

    一)关于加密算法 信息加密是现在几乎所有项目都需要用到的技术,身份认证.单点登陆.信息通讯.支付交易等场景中经常会需要用到加密算法,所谓加密算法,就是将原本的明文通过一系列算法操作变成密文.接下来就介 ...

  2. 熔化焊包括哪五种_常用的几种熔焊方法

    熔焊,是指焊接过程中,将焊接接头在高温等的作用下至熔化状态.由于被焊工件是紧密贴在一起的,在温度场.重力等的作用下,不加压力,两个工件熔化的融液会发生混合现象.待温度降低后,熔化部分凝结,两个工件就被 ...

  3. 浅析五种C语言内存分配的方法及区别

    点击上方蓝字关注我,了解更多咨询 在C语言中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区. 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区. ...

  4. Redis常用的五种数据类型

    转载 [Redis]五种数据类型及其使用场景 https://blog.csdn.net/zzu_seu/article/details/106323114?spm=1001.2101.3001.66 ...

  5. Java并发编程一线程池的五种状态

    推荐:Java并发编程汇总 Java并发编程一线程池的五种状态 原文地址 Java多线程线程池(4)–线程池的五种状态 正文 线程池的5种状态:Running.ShutDown.Stop.Tidyin ...

  6. redis五种数据类型及使用场景

    Redis 数据类型 转载自https://blog.csdn.net/zzu_seu/article/details/106323114 五种类型与类比java的模型 string --> S ...

  7. 线程的生命周期及五种基本状态介绍

    一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中的各知识点,Java中的多线程也就基本上掌 ...

  8. python各个解释器的用途-常用的五种Python解释器|老男孩网络Python学习课程

    Python是一门解释器语言,代码想运行,必须通过解释器执行,Python存在多种解释器,分别基于不同语言开发,每个解释器有不同的特点,但都能正常运行Python代码,以下是常用的五种Python解释 ...

  9. java clone方法_干货满满:Java中创建对象的五种方式详解

    通常来说,对象具有状态和行为,变量用来表明对象的状态,方法表明对象所具有的行为. 作为Java开发者,我们通常都是使用依赖管理系统,比如Spring去创建Java对象,但使用管理系统创建对象并不是唯一 ...

最新文章

  1. 删除驱动符号链接出错-变量作用域和RtlInitUnicodeString的问题
  2. 中国蚁剑(win32-x64)——安装报错:解压代码出错:[object Object]
  3. IOS开发之MD5加密和钥匙串的使用-oc
  4. html中如何设计对话框,用纯css3和html制作泡沫对话框实现代码
  5. c语言实现链表结构6,用c语言实现的链表结构--数据结构实验
  6. roobo机器人怎么唱歌_日本推出机器人“妻子”,拥有3大功能,能替代真人伴侣吗?...
  7. 解决Hbase报错java.lang.IllegalStateException: The procedure WAL relies on the ability to hsync for....
  8. k8s核心技术-Pod(调度策略)_影响Pod调度(节点亲和性)---K8S_Google工作笔记0026
  9. 抓包测试步骤XMind
  10. iOS app 启动 crash XCode 11 NSPOSIXErrorDomain Code=2 “No such file or directory“
  11. matlab 非线性辨识,非线性系统辨识Matlab实现
  12. 高等学校计算机一级考试题库,全国计算机一级考试题库「附答案」
  13. 教程篇(7.0) 01. FortiGate安全 简介及初始配置 ❀ Fortinet 网络安全专家 NSE 4
  14. java面试常见设计模式
  15. iOS 友盟登录和分享
  16. C语言指针,数组,函数
  17. 【Dash搭建可视化网站】项目13:销售数据可视化大屏制作步骤详解
  18. 系统级程序设计第一课
  19. 车载网络测试 - UDS诊断篇 - 诊断RID/IOID($2F/$31)
  20. 【菜鸟窝出品】 python的变量和逻辑基础(python数据分析入门)

热门文章

  1. 虚拟机查看cpu型号_CentOS7安装KVM虚拟机
  2. (78)FPGA内部资源与FPGA开发流程-面试必问(二)(第16天)
  3. (87)Verilog HDL:七分频设计
  4. STM32-SPI通信
  5. POSIX线程专有数据的空间释放问题,pthread_key_create
  6. Linux内核分析 - 网络[十]:ARP杂谈
  7. I2C总线信号时序总结
  8. C++中函数重载、缺省参数及命名空间
  9. 阴阳师服务器维护更新,阴阳师服务器3月10日维护更新了什么 阴阳师服务器3月10日维护更新一览...
  10. 西安工业大学计算机专业好吗,西安工业大学(专业学位)计算机技术考研难吗