Java中常用的加密方式(附多个工具类)

java

加密方式">一、Java常用加密方式

  • Base64加密算法(编码方式)
  • MD5加密(消息摘要算法,验证信息完整性)
  • 对称加密算法
  • 非对称加密算法
  • 数字签名算法
  • 数字证书

二、分类
按加密算法是否需要key被分为两类:

  1. 不基于key的有: Base64算法、MD5
  2. 基于key的有: 对称加密算法、非对称加密算法、数字签名算法、数字证书、HMAC、RC4(对称加密)

按加密算法是否可逆被分为两类:

  1. 单向加密算法(不可解密):MD5、SHA、HMAC
  2. 非单项加密算法(可解密):BASE64、对称加密算法、非对称加密算法、数字签名算法、数字证书

三、算法介绍
1.对称加密

对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。对称加密有很多种算法,由于它效率很高,所以被广泛使用在很多加密协议的核心当中。

对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。如果你只用1 bit来做这个密钥,那黑客们可以先试着用0来解密,不行的话就再用1解;但如果你的密钥有1 MB大,黑客们可能永远也无法破解,但加密和解密的过程要花费很长的时间。密钥的大小既要照顾到安全性,也要照顾到效率,是一个trade-off。

DES(Data Encryption Standard)和TripleDES是对称加密的两种实现。

DES和TripleDES基本算法一致,只是TripleDES算法提供的key位数更多,加密可靠性更高。
DES使用的密钥key为8字节,初始向量IV也是8字节。
TripleDES使用24字节的key,初始向量IV也是8字节。
两种算法都是以8字节为一个块进行加密,一个数据块一个数据块的加密,一个8字节的明文加密后的密文也是8字节。如果明文长度不为8字节的整数倍,添加值为0的字节凑满8字节整数倍。所以加密后的密文长度一定为8字节的整数倍

下面举个例子:

import java.security.InvalidKeyException;

import java.security.Key;

import java.security.NoSuchAlgorithmException;

import java.security.SecureRandom;

import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;

import javax.crypto.SecretKey;

import javax.crypto.SecretKeyFactory;

import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;

public class DESDemo {

// 算法名称

public static final String KEY_ALGORITHM = "DES";

// 算法名称/加密模式/填充方式

// DES共有四种工作模式-->>ECB:电子密码本模式、CBC:加密分组链接模式、CFB:加密反馈模式、OFB:输出反馈模式

public static final String CIPHER_ALGORITHM = "DES/ECB/NoPadding";

/**

*

* 生成密钥key对象

*

* @param KeyStr

* 密钥字符串

* @return 密钥对象

* @throws InvalidKeyException

* @throws NoSuchAlgorithmException

* @throws InvalidKeySpecException

* @throws Exception

*/

private static SecretKey keyGenerator(String keyStr) throws Exception {

byte input[] = HexString2Bytes(keyStr);

DESKeySpec desKey = new DESKeySpec(input);

// 创建一个密匙工厂,然后用它把DESKeySpec转换成

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");

SecretKey securekey = keyFactory.generateSecret(desKey);

return securekey;

}

private static int parse(char c) {

if (c >= 'a')

return (c - 'a' + 10) & 0x0f;

if (c >= 'A')

return (c - 'A' + 10) & 0x0f;

return (c - '0') & 0x0f;

}

// 从十六进制字符串到字节数组转换

public static byte[] HexString2Bytes(String hexstr) {

byte[] b = new byte[hexstr.length() / 2];

int j = 0;

for (int i = 0; i < b.length; i++) {

char c0 = hexstr.charAt(j++);

char c1 = hexstr.charAt(j++);

b[i] = (byte) ((parse(c0) << 4) | parse(c1));

}

return b;

}

/**

* 加密数据

*

* @param data

* 待加密数据

* @param key

* 密钥

* @return 加密后的数据

*/

public static String encrypt(String data, String key) throws Exception {

Key deskey = keyGenerator(key);

// 实例化Cipher对象,它用于完成实际的加密操作

Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

SecureRandom random = new SecureRandom();

// 初始化Cipher对象,设置为加密模式

cipher.init(Cipher.ENCRYPT_MODE, deskey, random);

byte[] results = cipher.doFinal(data.getBytes());

// 该部分是为了与加解密在线测试网站(http://tripledes.online-domain-tools.com/)的十六进制结果进行核对

for (int i = 0; i < results.length; i++) {

System.out.print(results[i] + " ");

}

System.out.println();

// 执行加密操作。加密后的结果通常都会用Base64编码进行传输

return Base64.encodeBase64String(results);

}

/**

* 解密数据

*

* @param data

* 待解密数据

* @param key

* 密钥

* @return 解密后的数据

*/

public static String decrypt(String data, String key) throws Exception {

Key deskey = keyGenerator(key);

Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

// 初始化Cipher对象,设置为解密模式

cipher.init(Cipher.DECRYPT_MODE, deskey);

// 执行解密操作

return new String(cipher.doFinal(Base64.decodeBase64(data)));

}

public static void main(String[] args) throws Exception {

String source = "helloittx";

System.out.println("原文: " + source);

String key = "A1B2C3D4E5F60708";

String encryptData = encrypt(source, key);

System.out.println("加密后: " + encryptData);

String decryptData = decrypt(encryptData, key);

System.out.println("解密后: " + decryptData);

}

}

2.非对称加密

非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人–银行才能对你的消息解密。与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。

目前最常用的非对称加密算法是RSA算法,是Rivest, Shamir, 和Adleman于1978年发明,他们那时都是在MIT。请看下面的例子:

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.math.BigInteger;

import java.security.Key;

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.SecureRandom;

import java.security.spec.RSAPrivateCrtKeySpec;

import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

import com.lxh.rsatest.HexUtil;

import Decoder.BASE64Decoder;

import Decoder.BASE64Encoder;

public class RSAEncrypt {

/** 指定加密算法为DESede */

private static String ALGORITHM = "RSA";

/** 指定key的大小 */

private static int KEYSIZE = 1024;

/** 指定公钥存放文件 */

private static String PUBLIC_KEY_FILE = "public.keystore";

/** 指定私钥存放文件 */

private static String PRIVATE_KEY_FILE = "private.keystore";

/**

* 生成密钥对

*/

private static void generateKeyPair() throws Exception {

/** RSA算法要求有一个可信任的随机数源 */

SecureRandom sr = new SecureRandom();

/** 为RSA算法创建一个KeyPairGenerator对象 */

KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);

/** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */

kpg.initialize(KEYSIZE, sr);

/** 生成密匙对 */

KeyPair kp = kpg.generateKeyPair();

/** 得到公钥 */

Key publicKey = kp.getPublic();

/** 得到私钥 */

Key privateKey = kp.getPrivate();

/** 用对象流将生成的密钥写入文件 */

ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));

ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));

oos1.writeObject(publicKey);

oos2.writeObject(privateKey);

/** 清空缓存,关闭文件输出流 */

oos1.close();

oos2.close();

}

/**

* 生成密钥对字符串

*/

private static void generateKeyPairString() throws Exception {

/** RSA算法要求有一个可信任的随机数源 */

SecureRandom sr = new SecureRandom();

/** 为RSA算法创建一个KeyPairGenerator对象 */

KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);

/** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */

kpg.initialize(KEYSIZE, sr);

/** 生成密匙对 */

KeyPair kp = kpg.generateKeyPair();

/** 得到公钥 */

Key publicKey = kp.getPublic();

/** 得到私钥 */

Key privateKey = kp.getPrivate();

/** 用字符串将生成的密钥写入文件 */

String algorithm = publicKey.getAlgorithm(); // 获取算法

KeyFactory keyFact = KeyFactory.getInstance(algorithm);

BigInteger prime = null;

BigInteger exponent = null;

RSAPublicKeySpec keySpec = (RSAPublicKeySpec) keyFact.getKeySpec(publicKey, RSAPublicKeySpec.class);

prime = keySpec.getModulus();

exponent = keySpec.getPublicExponent();

System.out.println("公钥模量:" + HexUtil.bytes2Hex(prime.toByteArray()));

System.out.println("公钥指数:" + HexUtil.bytes2Hex(exponent.toByteArray()));

System.out.println(privateKey.getAlgorithm());

RSAPrivateCrtKeySpec privateKeySpec = (RSAPrivateCrtKeySpec) keyFact.getKeySpec(privateKey,

RSAPrivateCrtKeySpec.class);

BigInteger privateModulus = privateKeySpec.getModulus();

BigInteger privateExponent = privateKeySpec.getPrivateExponent();

System.out.println("私钥模量:" + HexUtil.bytes2Hex(privateModulus.toByteArray()));

System.out.println("私钥指数:" + HexUtil.bytes2Hex(privateExponent.toByteArray()));

}

/**

* 加密方法 source: 源数据

*/

public static String encrypt(String source) throws Exception {

generateKeyPair();

/** 将文件中的公钥对象读出 */

ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));

Key key = (Key) ois.readObject();

ois.close();

String algorithm = key.getAlgorithm(); // 获取算法

KeyFactory keyFact = KeyFactory.getInstance(algorithm);

BigInteger prime = null;

BigInteger exponent = null;

if ("RSA".equals(algorithm)) { // 如果是RSA加密

RSAPublicKeySpec keySpec = (RSAPublicKeySpec) keyFact.getKeySpec(key, RSAPublicKeySpec.class);

prime = keySpec.getModulus();

exponent = keySpec.getPublicExponent();

// System.out.println("公钥模量:" + HexUtil.bytes2Hex(prime.toByteArray()));

// System.out.println("公钥指数:" + HexUtil.bytes2Hex(exponent.toByteArray()));

}

/** 得到Cipher对象来实现对源数据的RSA加密 */

Cipher cipher = Cipher.getInstance(ALGORITHM);

cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] b = source.getBytes();

/** 执行加密操作 */

byte[] b1 = cipher.doFinal(b);

BASE64Encoder encoder = new BASE64Encoder();

return encoder.encode(b1);

}

/**

* 解密算法 cryptograph:密文

*/

public static String decrypt(String cryptograph) throws Exception {

/** 将文件中的私钥对象读出 */

ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));

Key key = (Key) ois.readObject();

String algorithm = key.getAlgorithm(); // 获取算法

KeyFactory keyFact = KeyFactory.getInstance(algorithm);

RSAPrivateCrtKeySpec privateKeySpec = (RSAPrivateCrtKeySpec) keyFact.getKeySpec(key,

RSAPrivateCrtKeySpec.class);

BigInteger privateModulus = privateKeySpec.getModulus();

BigInteger privateExponent = privateKeySpec.getPrivateExponent();

// System.out.println("私钥模量:" + HexUtil.bytes2Hex(privateModulus.toByteArray()));

// System.out.println("私钥指数:" + HexUtil.bytes2Hex(privateExponent.toByteArray()));

/** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */

Cipher cipher = Cipher.getInstance(ALGORITHM);

cipher.init(Cipher.DECRYPT_MODE, key);

BASE64Decoder decoder = new BASE64Decoder();

byte[] b1 = decoder.decodeBuffer(cryptograph);

/** 执行解密操作 */

byte[] b = cipher.doFinal(b1);

return new String(b);

}

public static void main(String[] args) throws Exception {

generateKeyPair(); //生成文件形式公钥和私钥

//generateKeyPairString();//生成字符串形式公钥和私钥

String source = "非对称加密RSA";// 要加密的字符串

String cryptograph = encrypt(source);// 生成的密文

String hexCrypt = HexUtil.bytes2Hex(cryptograph.getBytes(), false);

System.out.println("生成的密文--->" + hexCrypt);

String target = decrypt(HexUtil.hex2String(hexCrypt));// 解密密文

System.out.println("解密密文--->" + target);

}

}

虽然非对称加密很安全,但是和对称加密比起来,它非常的慢,所以我们还是要用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。
(1) 对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。
(2) 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。
(3) 解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。

3.Base64编码

Base 64 Encoding有什么用?举个简单的例子,你使用SMTP协议 (Simple Mail Transfer Protocol 简单邮件传输协议)来发送邮件。因为这个协议是基于文本的协议,所以如果邮件中包含一幅图片,我们知道图片的存储格式是二进制数据(binary data),而非文本格式,我们必须将二进制的数据编码成文本格式,这时候Base 64 Encoding就派上用场了。

public void testJDKBase64(){

String encoderStr = java.util.Base64.getEncoder().encodeToString(s.getBytes());

System.out.println("encode :"+encoderStr);

String decodeStr = new String(java.util.Base64.getDecoder().decode(encoderStr));

System.out.println("decodeStr :"+decodeStr);

}

public void testCodecBase64(){

String encoderStr = org.apache.commons.codec.binary.Base64.encodeBase64String(s.getBytes());

System.out.println("encode :"+encoderStr);

String decodeStr = new String(org.apache.commons.codec.binary.Base64.decodeBase64(encoderStr));

System.out.println("decodeStr :"+decodeStr);

}

附工具类

package com.hl.bluetooth.util;

import org.springframework.boot.system.ApplicationHome;

import org.springframework.stereotype.Component;

import org.springframework.web.multipart.MultipartFile;

import sun.misc.BASE64Decoder;

import sun.misc.BASE64Encoder;

import java.io.*;

import java.util.Objects;

/**

* @DateL 2021/11/16 15:09

* @ClassName: FileUtils

**/

@Component

public class FileUtils {

public static File multipartFileToFile(MultipartFile multipartFile) {

File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));

try {

InputStream ins = null;

ins = multipartFile.getInputStream();

OutputStream os = new FileOutputStream(file);

int bytesRead = 0;

byte[] buffer = new byte[8192];

while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {

os.write(buffer, 0, bytesRead);

}

os.close();

ins.close();

} catch (Exception e) {

e.printStackTrace();

}

return file;

}

/**

* 图片转化成base64字符串

*

*/

public static String getImageStr(String imgPath) {

InputStream in = null;

byte[] data = null;

String encode = null;

// 对字节数组Base64编码

BASE64Encoder encoder = new BASE64Encoder();

try {

// 读取图片字节数组

in = new FileInputStream(imgPath);

data = new byte[in.available()];

in.read(data);

encode = encoder.encode(data);

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

in.close();

} catch (IOException e) {

e.printStackTrace();

}

}

return encode;

}

/**

* base64字符串转化成图片

*

* @param imgData 图片编码

*/

public static String generateImage(String imgData, String fileName) {

if (imgData == null) {

// 图像数据为空

return "null";

}

ApplicationHome applicationHome = new ApplicationHome(FileUtils.class);

File source = applicationHome.getSource();

String dirPath = source.getParentFile().toString() + "/upload";

BASE64Decoder decoder = new BASE64Decoder();

File dir = new File(dirPath);

if (!dir.exists()){

dir.mkdirs();

}

File file = new File(dirPath+"/"+fileName);

if (file.exists()){

file.delete();

}

try {

// Base64解码

byte[] b = decoder.decodeBuffer(imgData);

for (int i = 0; i < b.length; ++i) {

// 调整异常数据

if (b[i] < 0) {

b[i] += 256;

}

}

OutputStream out = new FileOutputStream(dirPath+"\\"+fileName);

out.write(b);

out.flush();

out.close();

return dirPath+"\\"+fileName;

} catch (Exception e) {

e.printStackTrace();

return "null";

}

}

}

4.MD5加密

Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992).

MD5的全称是Message-Digest Algorithm 5(信息-摘要算法),在90年代初由MIT Laboratory for Computer Science和RSA Data Security Inc的Ronald L. Rivest开发出来,经MD2、MD3和MD4发展而来。

MD5用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。

MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被”压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

/**

* Java消息摘要算法 MD5 工具类,其实其他摘要算法的实现也类似

*/

public class MD5Util {

/**

* 对文本执行 md5 摘要加密, 此算法与 mysql,JavaScript生成的md5摘要进行过一致性对比.

* @param plainText

* @return 返回值中的字母为小写

*/

public static String md5(String plainText) {

if (null == plainText) {

plainText = "";

}

String MD5Str = "";

try {

// JDK 6 支持以下6种消息摘要算法,不区分大小写

// md5,sha(sha-1),md2,sha-256,sha-384,sha-512

MessageDigest md = MessageDigest.getInstance("MD5");

md.update(plainText.getBytes());

byte b[] = md.digest();

int i;

StringBuilder builder = new StringBuilder(32);

for (int offset = 0; offset < b.length; offset++) {

i = b[offset];

if (i < 0)

i += 256;

if (i < 16)

builder.append("0");

builder.append(Integer.toHexString(i));

}

MD5Str = builder.toString();

// LogUtil.println("result: " + buf.toString());// 32位的加密

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

}

return MD5Str;

}

// 一个简版测试

public static void main(String[] args) {

String m1 = md5("1");

String m2 = md5(m1);

/* 输出为

* m1=c4ca4238a0b923820dcc509a6f75849b

* m2=28c8edde3d61a0411511d3b1866f0636

*/

System.out.println("m1="+m1);

System.out.println("m2="+m2);

}

}

通常我们不直接使用上述MD5加密。通常将MD5产生的字节数组交给Base64再加密一把,得到相应的字符串。

5.数字签名算法

签名:就有安全性,抗否认性
数字签名:带有密钥(公钥,私钥)的消息摘要算法
作用:
1. 验证数据的完整性
2. 认证数据来源
3. 抗否认

数字签名遵循:私钥签名,公钥验证
常用的数字签名算法:RSA,DSA,ECDSA

RSA介绍:

是经典算法,是目前为止使用最广泛的数字签名算法。

RSA数字签名算法的密钥实现与RSA的加密算法是一样的,算法的名称都叫RSA。密钥的产生和转换都是一样的。

RSA数字签名算法主要包括MD和SHA两类。

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.Signature;

import java.security.interfaces.RSAPrivateKey;

import java.security.interfaces.RSAPublicKey;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Hex;

public class RSATest {

public static final String src = "hello world";

public static void main(String[] args) {

jdkRSA();

}

/**

* 说明: 用java的jdk里面相关方法实现rsa的签名及签名验证

*/

public static void jdkRSA() {

try {

// 1.初始化密钥

KeyPairGenerator keyPairGenerator = KeyPairGenerator

.getInstance("RSA");

//设置KEY的长度

keyPairGenerator.initialize(512);

KeyPair keyPair = keyPairGenerator.generateKeyPair();

//得到公钥

RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();

//得到私钥

RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

// 2.进行签名

//用私钥进行签名

PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(

rsaPrivateKey.getEncoded());

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

//构造一个privateKey

PrivateKey privateKey = keyFactory

.generatePrivate(pkcs8EncodedKeySpec);

//声明签名的对象

Signature signature = Signature.getInstance("MD5withRSA");

signature.initSign(privateKey);

signature.update(src.getBytes());

//进行签名

byte[] result = signature.sign();

System.out.println("jdk rsa sign:" + Hex.encodeHexString(result));

// 3.验证签名

//用公钥进行验证签名

X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(

rsaPublicKey.getEncoded());

keyFactory = KeyFactory.getInstance("RSA");

//构造一个publicKey

PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

//声明签名对象

signature = Signature.getInstance("MD5withRSA");

signature.initVerify(publicKey);

signature.update(src.getBytes());

//验证签名

boolean bool = signature.verify(result);

System.out.println("jdk rsa verify:" + bool);

} catch (Exception e) {

System.out.println(e.toString());

}

}

}

四、应用场景
Base64应用场景:图片转码(应用于邮件,img标签,http加密)
MD5应用场景:密码加密、imei加密、文件校验
非对称加密:电商订单付款、银行相关业务

五、附多个工具类

AES

package com.hl.bluetooth.util;

import org.apache.commons.lang3.StringUtils;

import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

public class AesEncryptUtil {

//使用AES-128-CBC加密模式,key需要为16位,key和iv可以相同!

private final static String KEY = "ABCDEF1234432100";

private final static String IV = "43211234DCAB6789";

/**

* 加密方法

* @param data 要加密的数据

* @param key 加密key

* @param iv 加密iv

* @return 加密的结果

* @throws Exception

*/

public static String encrypt(String data, String key, String iv) throws Exception {

try {

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");//"算法/模式/补码方式"NoPadding PkcsPadding

int blockSize = cipher.getBlockSize();

byte[] dataBytes = data.getBytes();

int plaintextLength = dataBytes.length;

if (plaintextLength % blockSize != 0) {

plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));

}

byte[] plaintext = new byte[plaintextLength];

System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);

byte[] encrypted = cipher.doFinal(plaintext);

return new Base64().encodeToString(encrypted);

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

* 解密方法

* @param data 要解密的数据

* @param key 解密key

* @param iv 解密iv

* @return 解密的结果

* @throws Exception

*/

public static String desEncrypt(String data, String key, String iv) throws Exception {

try {

// byte[] encrypted1 = new Base64().decode(data);

byte[] encrypted1 = parseHexStr2Byte(data);

// Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

byte[] original = cipher.doFinal(encrypted1);

String originalString = new String(original);

return originalString;

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

* 使用默认的key和iv加密

* @param data

* @return

* @throws Exception

*/

public static String encrypt(String data) throws Exception {

return encrypt(data, KEY, IV);

}

/**

* 使用默认的key和iv解密

* @param data

* @return

* @throws Exception

*/

public static String desEncrypt(String data) throws Exception {

if (StringUtils.isEmpty(data)) {

return null;

}

return desEncrypt(data, KEY, IV);

}

/**

* @Author wdc

* @Description 16进制转byte数组

* @Date 2021/4/19 11:14

* @Param [hexStr]

* @return byte[]

**/

public static 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) {

// String test = "{'admin','admin'}";

//// String test =new String(test1.getBytes(),"UTF-8");

// String data = null;

// data = AesEncryptUtil.encrypt(test);

// System.out.println("数据:"+test);

// System.out.println("加密:"+data);

// String jiemi = AesEncryptUtil.desEncrypt(data);

// System.out.println("解密:"+jiemi);

}

}

base64

package com.sgitg.util;

import java.io.UnsupportedEncodingException;

import org.springframework.util.Base64Utils;

public class Base64Util {

/**

* 解码base64编码的字符串

*

* @param source

* @return

* @throws UnsupportedEncodingException

*/

public static String decodeFromString(String source) {

String str = "";

try {

byte[] bt = Base64Utils.decodeFromString(source);

str = new String(bt, "utf-8");

} catch (UnsupportedEncodingException e) {

e.printStackTrace(); // To change body of catch statement use File |

// Settings | File Templates.

}

return str;

}

/**

* 对字符串进行base64编码

*

* @param source

* @return

* @throws UnsupportedEncodingException

*/

public static String encodeToString(String source) {

byte[] bt = new byte[0];

try {

bt = source.getBytes("utf-8");

} catch (UnsupportedEncodingException e) {

e.printStackTrace(); // To change body of catch statement use File |

// Settings | File Templates.

}

return Base64Utils.encodeToString(bt);

}

}

EncryptUtils (编码集合)

* 1、Base64编码
* 1、AES、DES可逆算法
* 2、md5,Hex,Sha不可逆算法加密

package com.sgitg.util;

import org.apache.commons.codec.digest.DigestUtils;

import javax.crypto.Cipher;

import javax.crypto.KeyGenerator;

import javax.crypto.SecretKey;

import javax.crypto.spec.SecretKeySpec;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.nio.MappedByteBuffer;

import java.nio.channels.FileChannel;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

import java.security.SecureRandom;

import java.util.Base64;

import java.util.zip.CRC32;

/**

* 数据加密

* 继承org.apache.commons.codec.digest.DigestUtils

* 1、Base64编码

* 1、AES、DES可逆算法

* 2、md5,Hex,Sha不可逆算法加密

*

* @author liuyadu

*/

public class EncryptUtils extends DigestUtils {

/**

* 计算大文件 md5获取getMD5(); SHA1获取getSha1() CRC32获取 getCRC32()

*/

private static char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',

'f'};

// 测试

public static void main(String[] args) {

String en = encryptDES("hahahaha", "yaer");

String de = decryptDES("kzWPLLyAsDeBr84lL2COsA==", "yaer");

System.out.println(de);

System.out.println(en);

en = encryptAES("hahahaha", "yaer");

de = decryptAES("FBC82B89BAA1FBBDF3AE086A09D57E7C", "yaer");

System.out.println(de);

System.out.println(en);

}

/**

* AES加密(可逆)

*

* @param plainText 明文

* @param privateKey 密钥

* @return

* @throws NoSuchAlgorithmException

*/

public static String encryptAES(String plainText, String privateKey) {

try {

KeyGenerator kgen = KeyGenerator.getInstance("AES");

SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

random.setSeed(privateKey.getBytes());

kgen.init(128, random);

SecretKey secretKey = kgen.generateKey();

byte[] enCodeFormat = secretKey.getEncoded();

SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");

Cipher cipher = Cipher.getInstance("AES");

byte[] byteContent = plainText.getBytes("utf-8");

cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

byte[] byteRresult = cipher.doFinal(byteContent);

String sb = new String("");

for (int i = 0; i < byteRresult.length; i++) {

String hex = Integer.toHexString(byteRresult[i] & 0xFF);

if (hex.length() == 1) {

hex = '0' + hex;

}

sb = sb.concat(hex.toUpperCase());

}

return sb;

} catch (Exception e) {

return null;

}

}

/**

* AES解密

*

* @param cipherText 密文

* @param privateKey 密钥

* @return

* @throws Exception

*/

public static String decryptAES(String cipherText, String privateKey) {

try {

if (cipherText.length() < 1) {

return null;

}

byte[] byteRresult = new byte[cipherText.length() / 2];

for (int i = 0; i < cipherText.length() / 2; i++) {

int high = Integer.parseInt(cipherText.substring(i * 2, i * 2 + 1), 16);

int low = Integer.parseInt(cipherText.substring(i * 2 + 1, i * 2 + 2), 16);

byteRresult[i] = (byte) (high * 16 + low);

}

KeyGenerator kgen = KeyGenerator.getInstance("AES");

SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

random.setSeed(privateKey.getBytes());

kgen.init(128, random);

SecretKey secretKey = kgen.generateKey();

byte[] enCodeFormat = secretKey.getEncoded();

SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");

Cipher cipher = Cipher.getInstance("AES");

cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

byte[] result = cipher.doFinal(byteRresult);

return new String(result);

} catch (Exception e) {

return null;

}

}

/**

* 加密DES(可逆)

*

* @param plainText 明文

* @param privateKey 密钥

* @return

*/

public static String encryptDES(String plainText, String privateKey) {

try {

KeyGenerator keygen = KeyGenerator.getInstance("DES");

SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");

secureRandom.setSeed(privateKey.getBytes());

keygen.init(56, secureRandom);

SecretKey secretKey = keygen.generateKey();

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher.init(Cipher.ENCRYPT_MODE, secretKey);

byte[] cipherBytes = cipher.doFinal(plainText.getBytes("utf-8"));

byte[] plainTextBytes = Base64.getEncoder().encode(cipherBytes);

return new String(plainTextBytes, "utf-8");

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

* 解密DES

*

* @param cipherText 密文

* @param privateKey 密钥

* @return

*/

public static String decryptDES(String cipherText, String privateKey) {

try {

KeyGenerator keygen = KeyGenerator.getInstance("DES");

SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");

secureRandom.setSeed(privateKey.getBytes());

keygen.init(56, secureRandom);

SecretKey secretKey = keygen.generateKey();

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher.init(Cipher.DECRYPT_MODE, secretKey);

byte[] cipherTextBytes = Base64.getDecoder().decode(cipherText.getBytes("utf-8"));

byte[] cipherBytes = cipher.doFinal(cipherTextBytes);

return new String(cipherBytes, "utf-8");

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

* 获取文件md5值

*

* @return md5串

*/

public static String md5(File file) {

try {

//encrypt

MessageDigest messagedigest = MessageDigest.getInstance("MD5");

FileInputStream in = new FileInputStream(file);

FileChannel ch = in.getChannel();

MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());

messagedigest.update(byteBuffer);

return bufferToHex(messagedigest.digest());

} catch (Exception e) {

return null;

}

}

/***

* 获取文件SHA1值

*

* @return String 适用于上G大的文件

*/

public static String sha1(File file) {

try {

MessageDigest messagedigest = MessageDigest.getInstance("SHA-1");

FileInputStream in = new FileInputStream(file);

FileChannel ch = in.getChannel();

MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());

messagedigest.update(byteBuffer);

return bufferToHex(messagedigest.digest());

} catch (Exception e) {

return null;

}

}

/**

* 获取文件SHA256值

*

* @return String

*/

public static String sha256(File file) {

try {

MessageDigest messagedigest = MessageDigest.getInstance("SHA-256");

FileInputStream in = new FileInputStream(file);

FileChannel ch = in.getChannel();

MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());

messagedigest.update(byteBuffer);

return bufferToHex(messagedigest.digest());

} catch (Exception e) {

return null;

}

}

/**

* 获取文件CRC32码

*

* @return String

*/

public static String crc32(File file) {

CRC32 crc32 = new CRC32();

// MessageDigest.get

FileInputStream fileInputStream = null;

try {

fileInputStream = new FileInputStream(file);

byte[] buffer = new byte[8192];

int length;

while ((length = fileInputStream.read(buffer)) != -1) {

crc32.update(buffer, 0, length);

}

return crc32.getValue() + "";

} catch (FileNotFoundException e) {

e.printStackTrace();

return null;

} catch (IOException e) {

e.printStackTrace();

return null;

} finally {

try {

if (fileInputStream != null) {

fileInputStream.close();

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 计算二进制数据

*

* @return

*/

private static String bufferToHex(byte bytes[]) {

return bufferToHex(bytes, 0, bytes.length);

}

private static String bufferToHex(byte bytes[], int m, int n) {

StringBuffer stringbuffer = new StringBuffer(2 * n);

int k = m + n;

for (int l = m; l < k; l++) {

appendHexPair(bytes[l], stringbuffer);

}

return stringbuffer.toString();

}

private static void appendHexPair(byte bt, StringBuffer stringbuffer) {

char c0 = hexDigits[(bt & 0xf0) >> 4];

char c1 = hexDigits[bt & 0xf];

stringbuffer.append(c0);

stringbuffer.append(c1);

}

}

 

 

以上是 Java中常用的加密方式(附多个工具类) 的全部内容, 来源链接: utcz.com/z/394077.html

回到顶部