南宁网站设计要多少钱,网站页面布局名称,京津冀协同发展的路径主要涉及,网站子站建设自查报告转自#xff1a; https://blog.csdn.net/wqwqwqwq403/article/details/103948952 工作中经常会接触到一些加密算法#xff0c;比如说base64、MD5、DES、AES等等#xff0c;那么这些算法到底有什么区别以及具体的应用场景是什么呢#xff0c;下面就做个简要的梳理。
一、什…转自 https://blog.csdn.net/wqwqwqwq403/article/details/103948952 工作中经常会接触到一些加密算法比如说base64、MD5、DES、AES等等那么这些算法到底有什么区别以及具体的应用场景是什么呢下面就做个简要的梳理。
一、什么是加/解密目的是什么
所谓加密就是对原来为明文的文件或数据按某种算法进行处理使其成为不可读的一段代码通常称为 “密文”。目的就是保护数据不被非法窃取、阅读。 所谓解密也就是加密的逆过程即将该密文信息转化为其原来数据的过程。 举个例子小王想给他的妻子写一封信如果在邮寄的过程中被他人截获那么就显而易见的将信息泄露掉。相反如果小王根据一个密码本将信的内容加密比如每一个汉字对应一个编码那么即使被别人截获因为没有密码本那么信息也不会泄露小王的妻子拿到加密后的信件后用密码本再一一翻译成可读的文本这个过程就是解密。
二、什么是加/解密算法
加密/解密过程中使用到的算法就是加密/解密算法。
三、加/解密算法的分类
根据加/解密过程是否可逆算法可以分为可逆加密算法和不可逆加密算法。 可逆算法包括DES、3DES、AES、RSA、DSA 不可逆加密算法包括SHA-1、MD5 对于可逆加密如果没有秘钥任何人拿到了密文后通过对应的可逆算法都可以解密这是不安全的。所以引入了秘钥加密的时候加入了秘钥接收方解密时需提供秘钥这样不知道秘钥就无法解密。 根据加解密使用的秘钥是否相同算法可以分为对称加密算法和非对称加密算法。 对称加解密使用的秘钥是一致的非对称加解密使用的秘钥是不一致的。
四、不可逆算法
4.1 MD5加密算法
MD5 用的是哈希函数。严格来说MD5不是一种加密算法而是摘要算法。无论是多长的输入MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)。完整的md5一般是32位国内常见的一种是动网的16位也就是只取32位md5的中间16位另外有一种是变化过的md5特征是全是数字长度可能是20位或者19。
它的典型应用是对一段信息产生信息摘要以 防止被篡改。 防止被篡改的意思是发送方用此算法对一段信息产生一个摘要串接收方也用此算法产生一个摘要串然后比较这两个摘要串的内容是否一致如果不一致我们就认为此信息在传输的过程中可能发生了篡改。 那么有没有可能我修改了信息内容修改后的内容产生的md5与修改之前是一致的呢md5防止篡改的关键在于它的碰撞算法以前一直没有找到所谓碰撞算法就是修改原来的文件同时保持修改后的文件和原文件md5一致。不过后来我国山东大学的杨教授搞定了碰撞算法。所以md5作为防篡改已经不可靠了。类似的sha1的碰撞算法最近也被攻克。 public static String getMd5(String source) throws NoSuchAlgorithmException {//1.获取MessageDigest对象MessageDigest digest MessageDigest.getInstance(md5);//2.执行加密操作byte[] bytes source.getBytes();//在MD5算法这得到的目标字节数组的特点长度固定为16byte[] targetBytes digest.digest(bytes);//3.声明字符数组char [] characters new char[]{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F};//4.遍历targetBytesStringBuilder builder new StringBuilder();for (byte b : targetBytes) {//5.取出b的高四位的值//先把高四位通过右移操作拽到低四位int high (b 4) 15;//6.取出b的低四位的值int low b 15;//7.以high为下标从characters中取出对应的十六进制字符char highChar characters[high];//8.以low为下标从characters中取出对应的十六进制字符char lowChar characters[low];builder.append(highChar).append(lowChar);}return builder.toString();}4.2 SHA-1加密算法
SHA1 是和 MD5 一样流行的 消息摘要算法然而 SHA1 比 MD5 的 安全性更强。对于长度小于 2 ^ 64 位的消息SHA1 会产生一个 160 位(40个字符)的 消息摘要。基于 MD5、SHA1 的信息摘要特性以及 不可逆 (一般而言)可以被应用在检查 文件完整性 以及 数字签名 等场景。
public static String shaEncode(String inStr) throws Exception {MessageDigest sha null;try {sha MessageDigest.getInstance(SHA);} catch (Exception e) {System.out.println(e.toString());e.printStackTrace();return ;}byte[] byteArray inStr.getBytes(UTF-8);byte[] md5Bytes sha.digest(byteArray);StringBuffer hexValue new StringBuffer();for (int i 0; i md5Bytes.length; i) {int val ((int) md5Bytes[i]) 0xff;if (val 16) {hexValue.append(0);}hexValue.append(Integer.toHexString(val));}return hexValue.toString();}
五、对称加密算法
5.1 DES算法
DESData Encryption Standard是一种分组密码算法明文按 64 位进行分组密钥长 64 位密钥事实上是 56 位参与 DES 运算第8、16、24、32、40、48、56、64 位是校验位分组后的明文组和 56 位的密钥按位替代或交换的方法形成密文组之后按照顺序将密文组连在一起各段数据之间互不影响。标准的DES密钥长度为64bit即8个字符超过8个字符则舍弃后面。比如用abcdefgh与abcdefghi加密是一样的结果。又因为有校验位的存在所以用12345678与13345678进行加密是一样的。 如果密钥长度不足会以指定的填充方式 比如PKCS7Padding 方式补足位 关于数据补位参考https://www.cnblogs.com/Lawson/archive/2012/05/20/2510781.html 因此破译 DES 加密算法实际上就是 搜索密钥的编码。对于56 位长度的密钥 来说如果用穷举法来进行搜索的话其运算次数为 2 ^ 56 次非常大的一个数。des原理描述 https://blog.csdn.net/qq_32445015/article/details/80184954
package com.inspur.incloudmanager.controller.util;import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.util.Base64;public class DESUtil {/*** 偏移变量固定占8位字节*/private final static String IV_PARAMETER 12345678;/*** 密钥算法*/private static final String ALGORITHM DES;/*** 加密/解密算法-工作模式-填充模式*/
// private static final String CIPHER_ALGORITHM DES/CBC/PKCS5Padding;private static final String CIPHER_ALGORITHM DES/ECB/PKCS5Padding;/*** 默认编码*/private static final String CHARSET utf-8;/*** 生成key** param password* return* throws Exception*/private static Key generateKey(String password) throws Exception {DESKeySpec dks new DESKeySpec(password.getBytes(CHARSET));SecretKeyFactory keyFactory SecretKeyFactory.getInstance(ALGORITHM);return keyFactory.generateSecret(dks);}/*** DES加密字符串** param password 加密密码长度不能够小于8位* param data 待加密字符串* return 加密后内容*/public static String encrypt(String password, String data) {if (password null || password.length() 8) {throw new RuntimeException(加密失败key不能小于8位);}if (data null)return null;try {Key secretKey generateKey(password);Cipher cipher Cipher.getInstance(CIPHER_ALGORITHM);IvParameterSpec iv new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));//非ECB模式使用下面的偏移量
// cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);//ECB模式cipher.init(Cipher.ENCRYPT_MODE, secretKey);byte[] bytes cipher.doFinal(data.getBytes(CHARSET));//JDK1.8及以上可直接使用Base64JDK1.7及以下可以使用BASE64Encoder//Android平台可以使用android.util.Base64return new String(Base64.getEncoder().encode(bytes));} catch (Exception e) {e.printStackTrace();return data;}}/*** DES解密字符串** param password 解密密码长度不能够小于8位* param data 待解密字符串* return 解密后内容*/public static String decrypt(String password, String data) {if (password null || password.length() 8) {throw new RuntimeException(加密失败key不能小于8位);}if (data null)return null;try {Key secretKey generateKey(password);Cipher cipher Cipher.getInstance(CIPHER_ALGORITHM);IvParameterSpec iv new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));//非ECB模式使用下面的偏移量
// cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);cipher.init(Cipher.DECRYPT_MODE, secretKey);return new String(cipher.doFinal(Base64.getDecoder().decode(data.getBytes(CHARSET))), CHARSET);} catch (Exception e) {e.printStackTrace();return data;}}
}5.2 3DES算法
3DES又叫Triple DES是三重数据加密算法TDEATriple Data Encryption Algorithm块密码的通称。它相当于是对每个数据块应用三次DES加密算法。密钥长度是128位192位(bit)如果密码位数少于等于64位加密结果与DES相同。原版DES容易被破解新的3DES出现增加了加密安全性,避免被暴力破解。它同样是对称性加密同样涉及到加密编码方式及填充方式。包括3DES-ECB,3DES-CBC,3DES-CTR,3DES-OFB,3DES-CFB
public static String threedesencrypt(String key,String text) {try {byte[] src text.getBytes();DESedeKeySpec spec new DESedeKeySpec(convert(key.getBytes()));SecretKeyFactory factory SecretKeyFactory.getInstance(DESede);SecretKey secretKey factory.generateSecret(spec);Cipher cipher Cipher.getInstance(DESede/ECB/PKCS5Padding);cipher.init(Cipher.ENCRYPT_MODE, secretKey);byte[] res cipher.doFinal(src);//encodeBase64会对字符串3位一组自动补全因而最后可能会出现 或者 return new String(Base64.getEncoder().encode(res), utf-8);} catch (Exception e) {System.out.println(error);}return null;}/*** 不足24位进行补位* param sources* return*/private static byte[] convert(byte[] sources){byte[] ret new byte[24];if(sources.length 24){for(int i 0; i 24;i){if(i sources.length){ret[i] sources[i];}else{ret[i] 0;}}}else{ret sources;}return ret;}5.3 AES算法
高级加密标准英语Advanced Encryption Standard缩写AES是一种区块加密标准。这个标准用来替代原先的DES已经被多方分析且广为全世界所使用。 那么为什么原来的DES会被取代呢原因就在于其使用56位密钥比较容易被破解。而AES可以使用128、192、和256位密钥并且用128位分组加密和解密数据相对来说安全很多。完善的加密算法在理论上是无法破解的除非使用穷尽法。使用穷尽法破解密钥长度在128位以上的加密数据是不现实的仅存在理论上的可能性。统计显示即使使用目前世界上运算速度最快的计算机穷尽128位密钥也要花上几十亿年的时间更不用说去破解采用256位密钥长度的AES算法了。
package com.inspur.incloudmanager.controller.util;import org.springframework.util.Base64Utils;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger;public class AESUtil{private static final String KEY_ALGORITHM AES;private static final String DEFAULT_CIPHER_ALGORITHM AES/ECB/PKCS5Padding;//默认的加密算法/*** AES 加密操作** param content 待加密内容* param key 加密密钥* return 返回Base64转码后的加密数据*/public static String encrypt(String content, String key) {try {Cipher cipher Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器byte[] byteContent content.getBytes(utf-8);cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));// 初始化为加密模式的密码器byte[] result cipher.doFinal(byteContent);// 加密return Base64Utils.encodeToString(result);//通过Base64转码返回} catch (Exception ex) {Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);}return null;}/*** AES 解密操作** param content* param key* return*/public static String decrypt(String content, String key) {try {//实例化Cipher cipher Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);//使用密钥初始化设置为解密模式cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));//执行操作byte[] result cipher.doFinal(Base64Utils.decodeFromString(content));return new String(result, utf-8);} catch (Exception ex) {Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);}return null;}/*** 生成加密秘钥** return*/private static SecretKeySpec getSecretKey(final String key) {//返回生成指定算法密钥生成器的 KeyGenerator 对象KeyGenerator kg null;try {kg KeyGenerator.getInstance(KEY_ALGORITHM);//AES 要求密钥长度为 128kg.init(128, new SecureRandom(key.getBytes()));//生成一个密钥SecretKey secretKey kg.generateKey();return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥} catch (NoSuchAlgorithmException ex) {Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);}return null;}public static void main(String[] args) {String content Inspur1!;String key wang;System.out.println(content: content);String s1 AESUtil.encrypt(content, key);System.out.println(s1: s1);System.out.println(s2:AESUtil.decrypt(s1, key));}}
指定秘钥
public class AESUtil{private static final String KEY_ALGORITHM AES;private static final String DEFAULT_CIPHER_ALGORITHM AES/ECB/PKCS5Padding;//默认的加密算法/*** AES 加密操作** param content 待加密内容* param key 加密密钥* return 返回Base64转码后的加密数据*/public static String encrypt(String content, String key) {try {Cipher cipher Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器byte[] byteContent content.getBytes(utf-8);SecretKeySpec aeskey new SecretKeySpec(convert(key.getBytes(utf-8)), AES);cipher.init(Cipher.ENCRYPT_MODE, aeskey);// 初始化为加密模式的密码器byte[] result cipher.doFinal(byteContent);// 加密return Base64Utils.encodeToString(result);//通过Base64转码返回} catch (Exception ex) {Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);}return null;}/*** AES 解密操作** param content* param key* return*/public static String decrypt(String content, String key) {try {//实例化Cipher cipher Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);SecretKeySpec aeskey new SecretKeySpec(convert(key.getBytes(UTF-8)), AES);//使用密钥初始化设置为解密模式cipher.init(Cipher.DECRYPT_MODE, aeskey);//执行操作byte[] result cipher.doFinal(Base64Utils.decodeFromString(content));return new String(result, utf-8);} catch (Exception ex) {Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);}return null;}/*** 截取算法超过128位32字节手动截取掉* param sources* return*/private static byte[] convert(byte[] sources){byte[] ret new byte[32];if(sources.length 32){for(int i 0; i 32;i){ret[i] sources[i];}}else{ret sources;}return ret;}public static void main(String[] args) {String content Inspur1!;String key inclouqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq;System.out.println(content: content);String s1 AESUtil.encrypt(content, key);System.out.println(s1: s1);System.out.println(s2:AESUtil.decrypt(s1, key));}
}六、非对称加密算法
6.1 RSA算法
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;/*** RSA非对称加密算法工具类** author lixk*/public class RSA {//非对称密钥算法private static final String KEY_ALGORITHM RSA;//密钥长度在512到65536位之间建议不要太长否则速度很慢生成的加密数据很长private static final int KEY_SIZE 512;//字符编码private static final String CHARSET UTF-8;/*** 生成密钥对** return KeyPair 密钥对*/public static KeyPair getKeyPair() throws Exception {return getKeyPair(null);}/*** 生成密钥对* param password 生成密钥对的密码* return* throws Exception*/public static KeyPair getKeyPair(String password) throws Exception {//实例化密钥生成器KeyPairGenerator keyPairGenerator KeyPairGenerator.getInstance(KEY_ALGORITHM);//初始化密钥生成器if(password null){keyPairGenerator.initialize(KEY_SIZE);}else {SecureRandom secureRandom SecureRandom.getInstance(SHA1PRNG);secureRandom.setSeed(password.getBytes(CHARSET));keyPairGenerator.initialize(KEY_SIZE, secureRandom);}//生成密钥对return keyPairGenerator.generateKeyPair();}/*** 取得私钥** param keyPair 密钥对* return byte[] 私钥*/public static byte[] getPrivateKeyBytes(KeyPair keyPair) {return keyPair.getPrivate().getEncoded();}/*** 取得Base64编码的私钥** param keyPair 密钥对* return String Base64编码的私钥*/public static String getPrivateKey(KeyPair keyPair) {return Base64.getEncoder().encodeToString(getPrivateKeyBytes(keyPair));}/*** 取得公钥** param keyPair 密钥对* return byte[] 公钥*/public static byte[] getPublicKeyBytes(KeyPair keyPair) {return keyPair.getPublic().getEncoded();}/*** 取得Base64编码的公钥** param keyPair 密钥对* return String Base64编码的公钥*/public static String getPublicKey(KeyPair keyPair) {return Base64.getEncoder().encodeToString(getPublicKeyBytes(keyPair));}/*** 私钥加密** param data 待加密数据* param privateKey 私钥字节数组* return byte[] 加密数据*/public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {//实例化密钥工厂KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);//生成私钥PrivateKey key keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));//数据加密Cipher cipher Cipher.getInstance(KEY_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);}/*** 私钥加密** param data 待加密数据* param privateKey Base64编码的私钥* return String Base64编码的加密数据*/public static String encryptByPrivateKey(String data, String privateKey) throws Exception {byte[] key Base64.getDecoder().decode(privateKey);return Base64.getEncoder().encodeToString(encryptByPrivateKey(data.getBytes(CHARSET), key));}/*** 公钥加密** param data 待加密数据* param publicKey 公钥字节数组* return byte[] 加密数据*/public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {//实例化密钥工厂KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);//生成公钥PublicKey key keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));//数据加密Cipher cipher Cipher.getInstance(KEY_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);}/*** 公钥加密** param data 待加密数据* param publicKey Base64编码的公钥* return String Base64编码的加密数据*/public static String encryptByPublicKey(String data, String publicKey) throws Exception {byte[] key Base64.getDecoder().decode(publicKey);return Base64.getEncoder().encodeToString(encryptByPublicKey(data.getBytes(CHARSET), key));}/*** 私钥解密** param data 待解密数据* param privateKey 私钥字节数组* return byte[] 解密数据*/public static byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {//实例化密钥工厂KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);//生成私钥PrivateKey key keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));//数据解密Cipher cipher Cipher.getInstance(KEY_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, key);return cipher.doFinal(data);}/*** 私钥解密** param data Base64编码的待解密数据* param privateKey Base64编码的私钥* return String 解密数据*/public static String decryptByPrivateKey(String data, String privateKey) throws Exception {byte[] key Base64.getDecoder().decode(privateKey);return new String(decryptByPrivateKey(Base64.getDecoder().decode(data), key), CHARSET);}/*** 公钥解密** param data 待解密数据* param publicKey 公钥字节数组* return byte[] 解密数据*/public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {//实例化密钥工厂KeyFactory keyFactory KeyFactory.getInstance(KEY_ALGORITHM);//产生公钥PublicKey key keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));//数据解密Cipher cipher Cipher.getInstance(KEY_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, key);return cipher.doFinal(data);}/*** 公钥解密** param data Base64编码的待解密数据* param publicKey Base64编码的公钥* return String 解密数据*/public static String decryptByPublicKey(String data, String publicKey) throws Exception {byte[] key Base64.getDecoder().decode(publicKey);return new String(decryptByPublicKey(Base64.getDecoder().decode(data), key), CHARSET);}/*** 测试加解密方法** param args* throws Exception*/public static void main(String[] args) throws Exception {//生成密钥对一般生成之后可以放到配置文件中KeyPair keyPair RSA.getKeyPair();//公钥String publicKey RSA.getPublicKey(keyPair);//私钥String privateKey RSA.getPrivateKey(keyPair);System.out.println(公钥\n publicKey);System.out.println(私钥\n privateKey);String data RSA 加解密测试!;{System.out.println(\n私钥加密公钥解密);String s1 RSA.encryptByPrivateKey(data, privateKey);System.out.println(加密后的数据: s1);String s2 RSA.decryptByPublicKey(s1, publicKey);System.out.println(解密后的数据: s2 \n\n);}{System.out.println(\n公钥加密私钥解密);String s1 RSA.encryptByPublicKey(data, publicKey);System.out.println(加密后的数据: s1);String s2 RSA.decryptByPrivateKey(s1, privateKey);System.out.println(解密后的数据: s2 \n\n);}}
}声明本文章主要将几种常用的加密算法及其java实现统一整理便于以后查看。大多数是转载参考网上的内容。如有侵权请告知。 参考文章列表如下
https://blog.csdn.net/u013314786/article/details/80324461