加解密总结
1,Base64(编码)
Base64 编码是我们程序开发中经常使用到的编码方法,它用 64 个可打印字符来表示二进制数据。这 64 个字符是:小写字母 a-z、大写字母 A-Z、数字 0-9、符号"+“、”/“(再加上作为垫字的”=",实际上是 65 个字符),其他所有符号都转换成这个字符集中的字符。Base64 编码通常用作存储、传输一些二进制数据编码方法,所以说它本质上是一种将二进制数据转成文本数据的方案
特征:可以解密,每次结果也是一样的
public class Base64Util { /** * 加密:利用Java中sun.misc.BASE64Encoder() * */ public static String encrypt(String key){ return new BASE64Encoder().encode(key.getBytes()); } /** * 解密:利用Java中sun.misc.BASE64Encoder() * */ public static String decrypt(String str) throws IOException { return new String(new BASE64Decoder().decodeBuffer(str)); } /** * 加密:Base64.encode() * */ public static String encrypt1(String key){ return Base64.encode(key); } /** * 解密:Base64.decode() * */ public static String decrypt1(String key){ return new String(Base64.decode(key)); } }
2,凯撒加密(编码)
简单,经常作为其他加密的一个过程
public class KaisaUtil { /*** * 使用凯撒加密方式加密数据 * @param orignal 原文 * @param key 密钥 * @return 加密后的字符 */ public static String encryptKaisa(String orignal, int key) { //将字符串转换为数组 char[] chars = orignal.toCharArray(); StringBuffer buffer = new StringBuffer(); //遍历数组 for(char aChar : chars) { //获取字符的ASCII编码 int asciiCode = aChar; //偏移数据 asciiCode += key; //将偏移后的数据转为字符 char result = (char)asciiCode; //拼接数据 buffer.append(result); } return buffer.toString(); } /** * 使用凯撒加密方式解密数据 * * @param encryptedData :密文 * @param key :密钥 * @return : 源数据 */ public static String decryptKaiser(String encryptedData, int key) { // 将字符串转为字符数组 char[] chars = encryptedData.toCharArray(); StringBuilder sb = new StringBuilder(); // 遍历数组 for (char aChar : chars) { // 获取字符的ASCII编码 int asciiCode = aChar; // 偏移数据 asciiCode -= key; // 将偏移后的数据转为字符 char result = (char) asciiCode; // 拼接数据 sb.append(result); } return sb.toString(); } }
3,SHA(摘要加密)
单向,不可逆
public class SHAUtil { public static final String KEY_SHA = "SHA"; public static final String ALGORITHM256 = "SHA-256"; public static final String ALGORITHM384 = "SHA-384"; public static final String ALGORITHM512 = "SHA-512"; public static String encodeSHA(String data) throws NoSuchAlgorithmException { byte[] bytes = data.getBytes(); MessageDigest instance = MessageDigest.getInstance(ALGORITHM512); String result = new BASE64Encoder().encode( instance.digest(bytes)); return result; } }
4,MD5(摘要加密)
MD5 是将任意长度的数据字符串转化成短小的固定长度的值的单向操作,任意两个字符串不应有相同的散列值。因此 MD5 经常用于校验字符串或者文件,因为如果文件的 MD5 不一样,说明文件内容也是不一样的,如果发现下载的文件和给定的 MD5 值不一样,就要慎重使用。
MD5 主要用做数据一致性验证、数字签名和安全访问认证,而不是用作加密。比如说用户在某个网站注册账户时,输入的密码一般经过 MD5 编码,更安全的做法还会加一层盐(salt),这样密码就具有不可逆性。然后把编码后的密码存入数据库,下次登录的时候把密码 MD5 编码,然后和数据库中的作对比,这样就提升了用户账户的安全性。
特征:单向加密,不能解密,每次加密都是一样的
public class Md5Util { //盐,可自己定义 public static final String salt = "yanqi"; /** * Spring 的 DigestUtils */ public static String encrypt(String str){ //32位,小写 String md532Lower = DigestUtils.md5DigestAsHex("adcdefg".getBytes()); return DigestUtils.md5DigestAsHex((salt + md532Lower).getBytes()); } /** * JAVA 的 MessageDigest 加密 * */ public static String encrypt1(String str) throws NoSuchAlgorithmException { MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(str.getBytes()); return new BigInteger(1, md5.digest()).toString(16); } }
5,DES(对称加密)
对称加密算法就是:加密和解密使用相同密钥的算法
public class DESUtil { private static Key key; private static String KEY_STR="myYanqi"; private static String CHARSETNAME="UTF-8"; private static String ALGORITHM="DES"; static{ try { //生成DES算法对象 KeyGenerator generator=KeyGenerator.getInstance(ALGORITHM); //运用SHA1安全策略 SecureRandom secureRandom=SecureRandom.getInstance("SHA1PRNG"); //设置上密钥种子 secureRandom.setSeed(KEY_STR.getBytes()); //初始化基于SHA1的算法对象 generator.init(secureRandom); //生成密钥对象 key=generator.generateKey(); } catch (Exception e) { throw new RuntimeException(e); } } //加密 public static String encrypt(String str){ //基于BASE64编码,接收byte[]并转换成String BASE64Encoder encoder = new BASE64Encoder(); try { //按utf8编码 byte[] bytes = str.getBytes(CHARSETNAME); //获取加密对象 Cipher cipher = Cipher.getInstance(ALGORITHM); //初始化密码信息 cipher.init(Cipher.ENCRYPT_MODE, key); //加密 byte[] doFinal = cipher.doFinal(bytes); //byte[]to encode好的String 并返回 return encoder.encode(doFinal); } catch (Exception e) { throw new RuntimeException(e); } } //解密 public static String decrypt(String str){ BASE64Decoder decoder = new BASE64Decoder(); try { //将字符串decode成byte[] byte[] bytes = decoder.decodeBuffer(str); //获取解密对象 Cipher cipher = Cipher.getInstance(ALGORITHM); //初始化解密信息 cipher.init(Cipher.DECRYPT_MODE, key); //解密 byte[] doFial = cipher.doFinal(bytes); return new String(doFial, CHARSETNAME); } catch (Exception e) { throw new RuntimeException(e); } } }
6,AES(对称加密)
AES 与 DES 一样,一共有四种加密模式:
- 电子密码本模式(ECB)、
- 加密分组链接模式(CBC)、
- 加密反馈模式(CFB)
- 输出反馈模式(OFB)。
public class AESUtil { public static final String algorithm = "AES"; // AES/CBC/NOPaddin // AES 默认模式 // 使用CBC模式, 在初始化Cipher对象时, 需要增加参数, 初始化向量IV : IvParameterSpec iv = new // IvParameterSpec(key.getBytes()); // NOPadding: 使用NOPadding模式时, 原文长度必须是8byte的整数倍 public static final String transformation = "AES/CBC/PKCS5Padding"; public static final String key = "1234567812345678"; /*** * 加密 * @param original 需要加密的参数(注意必须是16位) * @return * @throws Exception */ public static String encryptByAES(String original) throws Exception { // 获取Cipher Cipher cipher = Cipher.getInstance(transformation); // 生成密钥 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), algorithm); // 指定模式(加密)和密钥 // 创建初始化向量 IvParameterSpec iv = new IvParameterSpec(key.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); // cipher.init(Cipher.ENCRYPT_MODE, keySpec); // 加密 byte[] bytes = cipher.doFinal(original.getBytes()); return new BASE64Encoder().encode(bytes); } /** * 解密 * @param encrypted 需要解密的参数 * @return * @throws Exception */ public static String decryptByAES(String encrypted) throws Exception { // 获取Cipher Cipher cipher = Cipher.getInstance(transformation); // 生成密钥 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), algorithm); // 指定模式(解密)和密钥 // 创建初始化向量 IvParameterSpec iv = new IvParameterSpec(key.getBytes()); cipher.init(Cipher.DECRYPT_MODE, keySpec, iv); // cipher.init(Cipher.DECRYPT_MODE, keySpec); // 解密 byte[] bytes = cipher.doFinal(new BASE64Decoder().decodeBuffer(encrypted)); return new String(bytes); } }
7,PBE(没用过)
public class PBEUtil { public static final String ALGORITHM = "PBEWITHMD5andDES"; public static final int ITERATION_COUNT = 100; public static byte[] initSalt() throws Exception{ //实例化安全随机数 SecureRandom random = new SecureRandom(); return random.generateSeed(8); } /*** * 转换密钥 * @param password 密码 * @return 密钥 * @throws Exception */ private static Key toKey(String password) throws Exception{ //密钥材料 PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray()); //实例化 SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM); //生成密钥 return factory.generateSecret(keySpec); } /*** * 加密 * @param data 待加密数据 * @param password 密钥 * @param salt * @return * @throws Exception */ public static byte[] encrypt(byte[] data, String password, byte[] salt) throws Exception{ //转换密钥 Key key = toKey(password); //实例化PBE参数材料 PBEParameterSpec spec = new PBEParameterSpec(salt, ITERATION_COUNT); //实例化 Cipher cipher = Cipher.getInstance(ALGORITHM); //初始化 cipher.init(Cipher.ENCRYPT_MODE, key, spec); return cipher.doFinal(data); } /*** * 解密 * @param data 待解密数据 * @param password 密钥 * @param salt * @return * @throws Exception */ public static byte[] decrypt(byte[] data, String password, byte[] salt) throws Exception{ //转换密钥 Key key = toKey(password); //实例化PBE参数材料 PBEParameterSpec spec = new PBEParameterSpec(salt, ITERATION_COUNT); //实例化 Cipher cipher = Cipher.getInstance(ALGORITHM); //初始化 cipher.init(Cipher.DECRYPT_MODE, key, spec); //执行操作 return cipher.doFinal(data); } public static String showByteArray(byte[] data) { if(null == data) { return null; } StringBuilder sb = new StringBuilder(); for(byte b : data) { sb.append(b).append(","); } sb.deleteCharAt(sb.length()-1); return sb.toString(); } }
8,RSA(非对称加密)
公钥加密,提供公钥
私钥解密,自己用的
public class RSAUtil { public static final String PUBLIC_KEY = "PUBLIC_KEY"; public static final String PRIVATE_KEY = "PRIVATE_KEY"; private static final Base64.Encoder base64Encoder = Base64.getEncoder(); private static final Base64.Decoder base64Decoder = Base64.getDecoder(); private static final String ALGORITHM = "RSA"; /** * 签名算法 */ private static final String SIGN_TYPE = "SHA1withRSA"; /** * 密钥长度 */ private static final Integer KEY_LENGTH = 1024; /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /** * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; /** * 生成秘钥对,公钥和私钥 * * @return 秘钥键值对 * @throws Exception 创建秘钥对异常 */ public static Map<String, Key> genKeyPair() throws Exception { Map<String, Key> keyMap = new HashMap<>(); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM); keyPairGenerator.initialize(KEY_LENGTH); // 秘钥字节数 KeyPair keyPair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * 公钥加密 * * @param data 加密前数据 * @param publicKey 公钥 * @return 加密后数据 * @throws Exception 加密异常 */ public static byte[] encryptByPublicKey(byte[] data, PublicKey publicKey) throws Exception { // 加密数据,分段加密 Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, publicKey); int inputLength = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offset = 0; byte[] cache; int i = 0; while (inputLength - offset > 0) { if (inputLength - offset > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offset, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offset, inputLength - offset); } out.write(cache, 0, cache.length); i++; offset = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } public static byte[] encryptByPublicKey(byte[] data, String publicKeyBase64Encoded) throws Exception { return encryptByPublicKey(data, parseString2PublicKey(publicKeyBase64Encoded)); } /** * 私钥解密 * * @param data 解密前数据 * @param privateKey 私钥 * @return 解密后数据 * @throws Exception 解密异常 */ public static byte[] decryptByPrivateKey(byte[] data, PrivateKey privateKey) throws Exception { // 解密数据,分段解密 Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, privateKey); int inputLength = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offset = 0; byte[] cache; int i = 0; while (inputLength - offset > 0) { if (inputLength - offset > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(data, offset, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(data, offset, inputLength - offset); } out.write(cache); i++; offset = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } public static byte[] decryptByPrivateKey(byte[] data, String privateKeyBase64Encoded) throws Exception { return decryptByPrivateKey(data, parseString2PrivateKey(privateKeyBase64Encoded)); } /** * 创建签名 * * @param source 要签名的信息 * @param privateKey 私钥 * @return 签名 * @throws Exception 签名异常 */ public static byte[] createSign(String source, PrivateKey privateKey) throws Exception { Signature signet = Signature.getInstance(SIGN_TYPE); signet.initSign(privateKey); signet.update(source.getBytes()); return signet.sign(); } public static byte[] createSign(String source, String privateKeyBase64Encoded) throws Exception { return createSign(source, parseString2PrivateKey(privateKeyBase64Encoded)); } /** * 校验签名 * * @param expected 期望信息 * @param sign 签名 * @param publicKey 公钥 * @return 结果 * @throws Exception 校验异常 */ public static boolean checkSign(String expected, byte[] sign, PublicKey publicKey) throws Exception { Signature signetCheck = Signature.getInstance(SIGN_TYPE); signetCheck.initVerify(publicKey); signetCheck.update(expected.getBytes()); return signetCheck.verify(sign); } public static boolean checkSign(String expected, byte[] sign, String publicKeyBase64Encoded) throws Exception { return checkSign(expected, sign, parseString2PublicKey(publicKeyBase64Encoded)); } /** * 将base64格式的公钥转换为对象 * * @param publicKeyBase64Encoded base64的公钥 * @return 公钥 * @throws Exception 转换异常 */ public static PublicKey parseString2PublicKey(String publicKeyBase64Encoded) throws Exception { return KeyFactory.getInstance(ALGORITHM).generatePublic( new X509EncodedKeySpec(base64Decoder.decode(publicKeyBase64Encoded))); } /** * 将base64格式的私钥转换为对象 * * @param privateKeyBase64Encoded base64的私钥 * @return 私钥 * @throws Exception 转换异常 */ public static PrivateKey parseString2PrivateKey(String privateKeyBase64Encoded) throws Exception { return KeyFactory.getInstance(ALGORITHM).generatePrivate( new PKCS8EncodedKeySpec(base64Decoder.decode(privateKeyBase64Encoded))); } }
本文作者:primaryC
本文链接:https://www.cnblogs.com/cnff/p/17532821.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步