一个聚合的加解密工具类
来源:互联网 发布:linux下载mysql的命令 编辑:程序博客网 时间:2024/05/22 05:13
小序
字符串,byte[],文件等对象的加密和解密,是开发当中必不可少的操作。这里仅基于不同方式的加解密实现,为方便使用固聚合为一个工具类使用,且代码实现与前辈们的实现并没有什么太大的差别。有需要的亲可直接带走,如若有不正确的地方还望指正。
代码
import android.annotation.SuppressLint;import android.text.TextUtils;import android.util.Base64;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;import java.security.InvalidKeyException;import java.security.Key;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.security.NoSuchProviderException;import java.security.PrivateKey;import java.security.PublicKey;import java.security.SecureRandom;import java.security.Signature;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.InvalidKeySpecException;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.HashMap;import java.util.Map;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.KeyGenerator;import javax.crypto.NoSuchPaddingException;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESKeySpec;import javax.crypto.spec.SecretKeySpec;/** * 加解密工具 */public class EncryptUtil { private EncryptUtil() { throw new UnsupportedOperationException("cannot be instantiated"); } /** * 二进位组转十六进制字符串 * * @param buf 二进位组 * @return 十六进制字符串 */ private static String parseByte2HexStr(byte buf[]) { StringBuilder sb = new StringBuilder(); for (byte b : buf) { String hex = Integer.toHexString(b & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } /** * 十六进制字符串转二进位组 * * @param hexStr 十六进制字符串 * @return 二进位组 */ private 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; } /** * MD5加密 * * @param string 加密字符串 * @param slat 加密盐值key * @return 加密结果字符串 */ public static String md5(String string, String slat) { if (TextUtils.isEmpty(string)) return ""; try { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] bytes = md5.digest((string + slat).getBytes()); String result = ""; for (byte b : bytes) { String temp = Integer.toHexString(b & 0xff); if (temp.length() == 1) { temp = "0" + temp; } result += temp; } return result; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } /** * MD5加密 * * @param string 加密字符串 * @return 加密结果字符串 * @see #md5(String, String) */ public static String md5(String string) { return TextUtils.isEmpty(string) ? "" : md5(string, ""); } /** * MD5的IO文件加密类型 */ public static final int MD5_TYPE_IO = 0; /** * MD5的NIO文件加密类型 */ public static final int MD5_TYPE_NIO = 1; /** * MD5加密 * * @param file 加密文件 * @param style 加密文件类型:{@link #MD5_TYPE_NIO} ,{@link #MD5_TYPE_IO} * @return 加密结果字符串 */ public static String md5(File file, int style) { if (file == null || !file.isFile() || !file.exists()) return ""; FileInputStream in = null; String result = ""; byte buffer[] = new byte[8192]; int len; try { in = new FileInputStream(file); MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] bytes = md5.digest(); if (style == MD5_TYPE_IO) { while ((len = in.read(buffer)) != -1) { md5.update(buffer, 0, len); } } else { MappedByteBuffer byteBuffer = in.getChannel().map( FileChannel.MapMode.READ_ONLY, 0, file.length()); md5.update(byteBuffer); } for (byte b : bytes) { String temp = Integer.toHexString(b & 0xff); if (temp.length() == 1) { temp = "0" + temp; } result += temp; } } catch (Exception e) { e.printStackTrace(); } finally { if (null != in) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } /** * MD5加密 * * @param string 加密字符串 * @param times 重复加密次数 * @return 加密结果字符串 */ public static String md5(String string, int times) { if (TextUtils.isEmpty(string)) return ""; String md5 = md5(string); for (int i = 0; i < times; i++) md5 = md5(md5); return md5; } /** * Base64加密 * * @param string 加密字符串 * @return 加密结果字符串 */ public static String base64EncodeStr(String string) { if (TextUtils.isEmpty(string)) return ""; return Base64.encodeToString(string.getBytes(), Base64.DEFAULT); } /** * Base64解密 * * @param string 解密字符串 * @return 解密结果字符串 */ public static String base64DecodedStr(String string) { if (TextUtils.isEmpty(string)) return ""; return new String(Base64.decode(string, Base64.DEFAULT)); } /** * Base64加密 * * @param file 加密文件 * @return 加密结果字符串 */ public static String base64EncodeFile(File file) { if (null == file) return ""; try { FileInputStream inputFile = new FileInputStream(file); byte[] buffer = new byte[(int) file.length()]; inputFile.read(buffer); inputFile.close(); return Base64.encodeToString(buffer, Base64.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return ""; } /** * Base64解密 * * @param filePath 解密文件路径 * @param code 解密文件编码 * @return 解密结果文件 */ public static File base64DecodedFile(String filePath, String code) { if (TextUtils.isEmpty(filePath) || TextUtils.isEmpty(code)) { return null; } File desFile = new File(filePath); try { byte[] decodeBytes = Base64.decode(code.getBytes(), Base64.DEFAULT); FileOutputStream fos = new FileOutputStream(desFile); fos.write(decodeBytes); fos.close(); } catch (Exception e) { e.printStackTrace(); } return desFile; } /** * Aes加密/解密 * * @param content 字符串 * @param password 密钥 * @param type 加密:{@link Cipher#ENCRYPT_MODE},解密:{@link Cipher#DECRYPT_MODE} * @return 加密/解密结果字符串 */ public static String aes(String content, String password, int type) { try { KeyGenerator generator = KeyGenerator.getInstance("AES"); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", "Crypto"); secureRandom.setSeed(password.getBytes()); generator.init(128, secureRandom); SecretKey secretKey = generator.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); @SuppressLint("GetInstance") Cipher cipher = Cipher.getInstance("AES"); cipher.init(type, key); if (type == Cipher.ENCRYPT_MODE) { byte[] byteContent = content.getBytes("utf-8"); return parseByte2HexStr(cipher.doFinal(byteContent)); } else { byte[] byteContent = parseHexStr2Byte(content); return new String(cipher.doFinal(byteContent)); } } catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | UnsupportedEncodingException | InvalidKeyException | NoSuchPaddingException | NoSuchProviderException e) { e.printStackTrace(); } return null; } /** * Des加密/解密 * * @param content 字符串内容 * @param password 密钥 * @param type 加密:{@link Cipher#ENCRYPT_MODE},解密:{@link Cipher#DECRYPT_MODE} * @return 加密/解密结果 */ public static String des(String content, String password, int type) { try { SecureRandom random = new SecureRandom(); DESKeySpec desKey = new DESKeySpec(password.getBytes()); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); @SuppressLint("GetInstance") Cipher cipher = Cipher.getInstance("DES"); cipher.init(type, keyFactory.generateSecret(desKey), random); if (type == Cipher.ENCRYPT_MODE) { byte[] byteContent = content.getBytes("utf-8"); return parseByte2HexStr(cipher.doFinal(byteContent)); } else { byte[] byteContent = parseHexStr2Byte(content); return new String(cipher.doFinal(byteContent)); } } catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | UnsupportedEncodingException | InvalidKeyException | NoSuchPaddingException | InvalidKeySpecException e) { e.printStackTrace(); } return null; } /** * Sha加密类型 */ public final static String SHA224 = "sha-224"; /** * Sha加密类型 */ public final static String SHA256 = "sha-256"; /** * Sha加密类型 */ public final static String SHA384 = "sha-384"; /** * Sha加密类型 */ public final static String SHA512 = "sha-512"; /** * Sha加密 * * @param string 加密字符串 * @param type 加密类型 :{@link #SHA224},{@link #SHA256},{@link #SHA384},{@link #SHA512} * @return SHA加密结果字符串 */ public static String sha(String string, String type) { if (TextUtils.isEmpty(string)) return ""; if (TextUtils.isEmpty(type)) type = SHA256; try { MessageDigest md5 = MessageDigest.getInstance(type); byte[] bytes = md5.digest((string).getBytes()); String result = ""; for (byte b : bytes) { String temp = Integer.toHexString(b & 0xff); if (temp.length() == 1) { temp = "0" + temp; } result += temp; } return result; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } /** * 随机获取密钥(公钥和私钥), 客户端公钥加密,服务器私钥解密 * * @return 结果密钥对 * @throws Exception */ public static Map<String, Object> genKeyPair() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA", "BC"); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap<>(2); keyMap.put("RSAPublicKey", publicKey); keyMap.put("RSAPrivateKey", privateKey); return keyMap; } /** * 获取公钥/私钥 * * @param keyMap 密钥对 * @param isPublicKey true:获取公钥,false:获取私钥 * @return 获取密钥字符串 */ public static String getKey(Map<String, Object> keyMap, boolean isPublicKey) { Key key = (Key) keyMap.get(isPublicKey ? "RSAPublicKey" : "RSAPrivateKey"); return new String(Base64.encode(key.getEncoded(), Base64.DEFAULT)); } /** * 获取数字签名 * * @param data 二进制位 * @param privateKey 私钥(BASE64编码) * @return 数字签名结果字符串 * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64.decode(privateKey.getBytes(), Base64.DEFAULT); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC"); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance("MD5withRSA"); signature.initSign(privateK); signature.update(data); return new String(Base64.encode(signature.sign(), Base64.DEFAULT)); } /** * 数值签名校验 * * @param data 二进位组 * @param publicKey 公钥(BASE64编码) * @param sign 数字签名字符串 * @return true:校验成功,false:校验失败 * @throws Exception */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { byte[] keyBytes = Base64.decode(publicKey.getBytes(), Base64.DEFAULT); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC"); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance("MD5withRSA"); signature.initVerify(publicK); signature.update(data); return signature.verify(Base64.decode(sign.getBytes(), Base64.DEFAULT)); } /** * Rsa公钥加密类型 */ public static final int RSA_PUBLIC_ENCRYPT = 0; /** * Rsa公钥解密类型 */ public static final int RSA_PUBLIC_DECRYPT = 1; /** * Rsa私钥加密类型 */ public static final int RSA_PRIVATE_ENCRYPT = 2; /** * Rsa私钥解密类型 */ public static final int RSA_PRIVATE_DECRYPT = 3; /** * Rsa加密/解密(一般情况下,公钥加密私钥解密) * * @param data 源数据 * @param string 密钥(BASE64编码) * @param type 操作类型:{@link #RSA_PUBLIC_ENCRYPT},{@link #RSA_PUBLIC_DECRYPT},{@link #RSA_PRIVATE_ENCRYPT},{@link #RSA_PRIVATE_DECRYPT} * @return 加密/解密结果字符串 * @throws Exception */ public static byte[] rsa(byte[] data, String string, int type) throws Exception { byte[] keyBytes = Base64.decode(string, Base64.DEFAULT); Key key; KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC"); if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) { X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); key = keyFactory.generatePublic(x509KeySpec); } else { PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); key = keyFactory.generatePrivate(pkcs8KeySpec); } // 对数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PRIVATE_ENCRYPT) { cipher.init(Cipher.ENCRYPT_MODE, key); while (inputLen - offSet > 0) { cache = cipher.doFinal(data, offSet, inputLen - offSet > 117 ? 117 : inputLen - offSet); out.write(cache, 0, cache.length); i++; offSet = i * 117; } } else { cipher.init(Cipher.DECRYPT_MODE, key); while (inputLen - offSet > 0) { if (inputLen - offSet > 128) { cache = cipher.doFinal(data, offSet, 128); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * 128; } } byte[] result = out.toByteArray(); out.close(); return result; }}
md5
// 字符串加密String str = "123456";System.out.println("一次加密:" + Encryption.md5(str));System.out.println("二次加密:" + Encryption.md5(str, 2));System.out.println("盐值加密:" + Encryption.md5(str, "78"));
System.out: 一次加密:e10adc3949ba59abbe56e057f20f883e
System.out: 二次加密:c56d0e9a7ccec67b4ea131655038d604
System.out: 盐值加密:25d55ad283aa400af464c76d713c07ad
// 文件加密Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);System.out.println("IO文件加密:" + EncryptUtil.md5(getBitmap2File(bmp), EncryptUtil.MD5_TYPE_IO));System.out.println("NIO文件加密:" + EncryptUtil.md5(getBitmap2File(bmp), EncryptUtil.MD5_TYPE_NIO));
I/System.out: IO文件加密:d41d8cd98f00b204e9800998ecf8427e
I/System.out: NIO文件加密:d41d8cd98f00b204e9800998ecf8427e
Base64
// 字符串加解密String baseStr = EncryptUtil.base64EncodeStr("123456");System.out.println("base64字符串加密:" + baseStr);System.out.println("base64字符串解密:" + EncryptUtil.base64DecodedStr(baseStr));
I/System.out: base64字符串加密:MTIzNDU2
I/System.out: base64字符串解密:123456
// 文件加解密Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);String baseFile = EncryptUtil.base64EncodeFile(getBitmap2File(bmp));System.out.println("base64文件加密:" + baseFile);System.out.println("base64文件解密:" + EncryptUtil.base64DecodedFile("/mnt/sdcard/01.jpg", baseFile));
I/System.out: base64文件加密:
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB…I/System.out: base64文件解密:/mnt/sdcard/01.jpg
AES
// 对象加解密String key = "1234567890123456";String aesStr = EncryptUtil.aes("gzejia", key, Cipher.ENCRYPT_MODE);System.out.println("aes对象加密: " + aesStr);System.out.println("aes对象解密: " + EncryptUtil.aes(aesStr, key, Cipher.DECRYPT_MODE));
I/System.out: aes对象加密: 7E8886393DD34B24CC51B1A9D030DB5A
I/System.out: aes对象解密: gzejia
javax.crypto.BadPaddingException: pad block corrupted,出现该异常的主导原因可能如下:
- 密钥key长度不足16位
- 缺少 SecureRandom secureRandom = SecureRandom.getInstance(“SHA1PRNG”, “Crypto”);
DES
String key = "1234567890123456";String desStr = EncryptUtil.des("gzejia", key, Cipher.ENCRYPT_MODE);System.out.println("des对象加密: " + desStr);System.out.println("des对象解密: " + EncryptUtil.des(desStr, key, Cipher.DECRYPT_MODE));
I/System.out: des对象加密: 552E6962E5187580
I/System.out: des对象解密: gzejia
SHA
String shaStr = "gzejia";System.out.println("sha_SHA224对象加密: " + EncryptUtil.sha(shaStr, EncryptUtil.SHA224));System.out.println("sha_SHA256对象加密: " + EncryptUtil.sha(shaStr, EncryptUtil.SHA256));System.out.println("sha_SHA384对象加密: " + EncryptUtil.sha(shaStr, EncryptUtil.SHA384));System.out.println("sha_SHA512对象加密: " + EncryptUtil.sha(shaStr, EncryptUtil.SHA512));
I/System.out: sha_SHA224对象加密:
36e2a37256a87dda91e8dacf9662c49461ecfc68d65488857c146e59I/System.out: sha_SHA256对象加密:
94a9222df72d5927d1996203b0b186ab857d9055db54b48277bf943272b19fc1I/System.out: sha_SHA384对象加密:
ea8e751bdfccb96715a37153a831fc935e2986743de72b32941043c1960f2e2ab7d71b965dda42cd128a837191e4667aI/System.out: sha_SHA512对象加密:
a5e7bea71af1fccdc1f3d353df08013e2bebe8e0a49b435512bdc855f36589cffbf1ac1825e2357a4a4f8b5295173928f76a806ba0c77c2a7ba3ef068cdf3ced
RSA
try { byte[] data = "gzejia有中文".getBytes(); // 密钥与数字签名获取 Map<String, Object> keyMap = EncryptUtil.genKeyPair(); String publicKey = EncryptUtil.getKey(keyMap, true); System.out.println("rsa获取公钥: " + publicKey); String privateKey = EncryptUtil.getKey(keyMap, false); System.out.println("rsa获取私钥: " + privateKey); // 公钥加密私钥解密 byte[] rsaPublic = EncryptUtil.rsa(data, publicKey, EncryptUtil.RSA_PUBLIC_ENCRYPT); System.out.println("rsa公钥加密: " + new String(rsaPublic)); System.out.println("rsa私钥解密: " + new String( EncryptUtil.rsa(rsaPublic, privateKey, EncryptUtil.RSA_PRIVATE_DECRYPT))); // 私钥加密公钥解密 byte[] rsaPrivate = EncryptUtil.rsa(data, privateKey, EncryptUtil.RSA_PRIVATE_ENCRYPT); System.out.println("rsa私钥加密: " + new String(rsaPrivate)); System.out.println("rsa公钥解密: " + new String( EncryptUtil.rsa(rsaPrivate, publicKey, EncryptUtil.RSA_PUBLIC_DECRYPT))); // 私钥签名及公钥签名校验 String signStr = EncryptUtil.sign(rsaPrivate, privateKey); System.out.println("rsa数字签名生成: " + signStr); System.out.println("rsa数字签名校验: " + EncryptUtil.verify(rsaPrivate, publicKey, signStr));} catch (Exception e) { e.printStackTrace();}
I/System.out: rsa获取公钥:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3W84EWgATxN4OfjXUResyzy+lf/8TDDmHtRkh…I/System.out: rsa获取私钥:
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALdbzgRaABPE3g5+NdRF6zLPL6V/…I/System.out: rsa公钥加密:o�ZW�Ay����&�d��qa�h�]�ɟ�Ӵ�Rg1�0#…
I/System.out: rsa私钥解密: gzejia有中文
I/System.out: rsa私钥加密: � ��IA�{�R�+�y�_����%�=��…
I/System.out: rsa公钥解密: gzejia有中文
I/System.out: rsa数字签名生成:
XYHhwM2d+qUOWfTvi4l0Xh0JHlgf4zOBz81wahV90dxHhoqbi/HG6PlmkPnFnnZAkB5X8VMRKumK…I/System.out: rsa数字签名校验: true
java.security.spec.InvalidKeySpecException:
java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag,解决途径:
原语句: KeyFactory keyf = KeyFactory.getInstance(“RSA”);
更改为:KeyFactory keyFactory = KeyFactory.getInstance(“RSA”, “BC”);
- 一个聚合的加解密工具类
- 一个 AES 加解密工具类
- 加解密工具类
- 提供一个AES128位/CBC模式加解密工具类
- 简单的加解密工具
- DES加解密工具类
- AES加解密工具类
- java 加解密工具类
- DES加解密工具类
- DES加解密工具类
- DES加解密工具类
- 加解密的一个方法
- Cryptography,一个C#写的加解密算法的类
- 一个简单基于密匙的加解密类
- Java中实现DES加解密的一个类
- 一个java的DES加解密类转换成C#
- 【一个java的DES加解密类转换成C#】
- 【一个java的DES加解密类转换成C#】
- NOI 模拟试题(一)
- perl调用命令包含正则表达式,要注意转义符。[经验,还未证实]
- python中的静态类与方法
- 第35个python程序:分支和函数
- (android高仿系列)今日头条 --新闻阅读器 (二)
- 一个聚合的加解密工具类
- mysq数据从一个数据库的表复制到另一个数据库的表
- windows7中安装jdk1.8
- redis学习笔记
- IOS自动布局之Autoresizing
- linux下find(文件查找)命令的用法总结
- 自定义一个仿Spinner
- 【HDU】5859 Captain is coding【优先队列贪心】
- plsql日期显示问题