一、Java常用API之Base64加密与解密
在进行任何语言类库的设计过程之中,除了比较大型的类库结构之外,例如:国际化、正则表达式、字符串等,还会提供很多小类库,简单的理解为它可以完成部分的操作功能,而本文讨论的Base64就属于这样的一中小的类库功能。Base64是在软件设计过程中比较常见的一中数据的加密和解密的处理形式,这个类实在JDK1.8之后的版本菜开始提供的工具类。
为了数据的安全一般在网络上都会进行加密的方式进行数据的传输,一但加密之后就需要有特定的方式来进行解密的处理操作,Base64是一种数据的处理格式,不完全只是为了加密而存在,但是却可以实现加密的功能。
二、常用API
1、加密、解密
/*** 加密、解密*/@Testpublic void demo01() {String message = "www.baidu.com";//原始数据Base64.Encoder encoder = Base64.getEncoder();//加密工具类byte[] encode = encoder.encode(message.getBytes());//需要传字节数组对数据进行加密处理System.out.println("【加密后的数据】" + new String(encode));Base64.Decoder decoder = Base64.getDecoder();//解密工具类byte[] decode = decoder.decode(encode);//同样需要传入字节数组进行解密System.out.println("【解密后的数据】" + new String(decode));}
2、自定义数据加密的工具类
Base64并不属于私人的加密处理,而是属于一中在整个互联网上最为常见的一中数据的编码形式,所以如果现在纯粹使用以上的模式基本上是没有加密的意义的,如果要让这些数据存在加密的意义,最佳的做法一定是执行多次的加密处理,同时为了保证数据更加安全,一般还建议在数据前追加一个盐值(salt)。
范例: 自定义数据加密的工具类
/*** 密码加密工具类*/public class PasswordUtil {private static final int REPEAT = 5; // 表示重复加密5次private static final String SALT = "www.baidu.com";// 追加操作盐值(真正应用的时候盐值要使用随机生成的字符串)private PasswordUtil(){}//该类的方法为static方法/*** 加密的方法* @param password 需要加密的字符串* @return 加密后的字符串*/public static String encrypt(String password){String encodeData = "{"+ SALT +"}" + password;Base64.Encoder encoder = Base64.getEncoder();//获得加密类对象for (int i = 0; i < REPEAT; i++) {encodeData = encoder.encodeToString(encodeData.getBytes());//执行加密操作}return encodeData;}/*** 解密的方法* @param password 加密后的字符串* @return 原始字符串数据*/public static String decrypt(String password){Base64.Decoder decoder = Base64.getDecoder();//获得解密类对象byte[] bytes = password.getBytes();//根据字节数组进行解密操作for (int i = 0; i < REPEAT; i++) {bytes = decoder.decode(bytes);//多次解密}String decodeData = new String(bytes);return decodeData.substring(("{"+ SALT +"}").length());}}
三、RSA非对称加密
1、秘钥生成工具类
/*** 非对称加密:* 用公钥加密,用私钥解密,并且公钥加密后的数据无法再用公钥解密* 生成两把密钥:公钥和私钥* 公钥用于加密,私钥用于解密*/public class RSAKeyCreater {/*** 注意:* 1、生成公钥和私钥* 2、公钥和私钥应该一起生成,否则加密后无法正确解密* 3、每次调用此方法生成的公钥和私钥都不相同* @return 公钥和私钥的集合*/public static Map<String, Object> createKeyPairs() {Map<String,Object> map = new HashMap<>(2);try {Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");generator.initialize(512, new SecureRandom());KeyPair pair = generator.generateKeyPair();PublicKey pubKey = pair.getPublic();PrivateKey privKey = pair.getPrivate();map.put("publicKey",pubKey);map.put("privateKey",privKey);} catch (Exception e) {e.printStackTrace();}return map;}}
2、加密解密工具类
/*** RSA加密解密类*/public class RsaUtil {/*** RSA加密* @param data 待加密数据* @param publicKey 公钥* @return 加密后的数据*/public static String encryptData(String data, PublicKey publicKey) {try {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] dataToEncrypt = data.getBytes("utf-8");byte[] encryptedData = cipher.doFinal(dataToEncrypt);String encryptString = Base64.encodeBase64String(encryptedData);return encryptString;} catch (Exception e) {e.printStackTrace();}return null;}/*** RSA解密* @param data 待解密数据* @param privateKey 私钥* @return 解密后的数据*/public static String decryptData(String data, PrivateKey privateKey) {try {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] descryptData = Base64.decodeBase64(data);byte[] descryptedData = cipher.doFinal(descryptData);String srcData = new String(descryptedData, "utf-8");return srcData;} catch (Exception e) {e.printStackTrace();}return null;}}
四、MD5
/*** MD5加密---不可逆*/public class MD5Utils {/*** 生成含有随机盐的密码* @param password 要加密的密码* @return String 加密后的含有随机盐的密码*/public static String getSaltMD5(String password) {// 生成一个16位的随机数Random random = new Random();StringBuilder sBuilder = new StringBuilder(16);sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));int len = sBuilder.length();if (len < 16) {for (int i = 0; i < 16 - len; i++) {sBuilder.append("0");}}// 生成最终的加密盐值String salt = sBuilder.toString();password = md5Hex(password + salt);char[] cs = new char[48];for (int i = 0; i < 48; i += 3) {cs[i] = password.charAt(i / 3 * 2);char c = salt.charAt(i / 3);cs[i + 1] = c;cs[i + 2] = password.charAt(i / 3 * 2 + 1);}return String.valueOf(cs);}/*** 验证加盐后是否和原密码一致* @param password 原密码* @param password 加密之后的密码* @return boolean true表示和原密码一致 false表示和原密码不一致*/public static boolean getSaltverifyMD5(String password, String md5str) {char[] cs1 = new char[32];char[] cs2 = new char[16];for (int i = 0; i < 48; i += 3) {cs1[i / 3 * 2] = md5str.charAt(i);cs1[i / 3 * 2 + 1] = md5str.charAt(i + 2);cs2[i / 3] = md5str.charAt(i + 1);}String Salt = new String(cs2);return md5Hex(password + Salt).equals(String.valueOf(cs1));}/*** byte[]字节数组 转换成 十六进制字符串* @param arr 要转换的byte[]字节数组* @return String 返回十六进制字符串*/private static String hex(byte[] arr) {StringBuilder sb = new StringBuilder();for (int i = 0; i < arr.length; ++i) {sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1, 3));}return sb.toString();}/*** MD5加密,并把结果由字节数组转换成十六进制字符串* @param str 要加密的内容* @return String 返回加密后的十六进制字符串*/private static String md5Hex(String str) {try {MessageDigest md = MessageDigest.getInstance("MD5");byte[] digest = md.digest(str.getBytes());return hex(digest);} catch (Exception e) {e.printStackTrace();}return "";}/*** 测试* @param args*/public static void main(String[] args) {// 原密码String plaintext = "admin";// 获取加盐后的MD5值String ciphertext = MD5Utils.getSaltMD5(plaintext);System.out.println("加盐后MD5:" + ciphertext);System.out.println("是否是同一字符串:" + MD5Utils.getSaltverifyMD5(plaintext, ciphertext));}}
