一、Java常用API之Base64加密与解密

在进行任何语言类库的设计过程之中,除了比较大型的类库结构之外,例如:国际化、正则表达式、字符串等,还会提供很多小类库,简单的理解为它可以完成部分的操作功能,而本文讨论的Base64就属于这样的一中小的类库功能。Base64是在软件设计过程中比较常见的一中数据的加密和解密的处理形式,这个类实在JDK1.8之后的版本菜开始提供的工具类。
为了数据的安全一般在网络上都会进行加密的方式进行数据的传输,一但加密之后就需要有特定的方式来进行解密的处理操作,Base64是一种数据的处理格式,不完全只是为了加密而存在,但是却可以实现加密的功能。

二、常用API

1、加密、解密

  1. /**
  2. * 加密、解密
  3. */
  4. @Test
  5. public void demo01() {
  6. String message = "www.baidu.com";//原始数据
  7. Base64.Encoder encoder = Base64.getEncoder();//加密工具类
  8. byte[] encode = encoder.encode(message.getBytes());//需要传字节数组对数据进行加密处理
  9. System.out.println("【加密后的数据】" + new String(encode));
  10. Base64.Decoder decoder = Base64.getDecoder();//解密工具类
  11. byte[] decode = decoder.decode(encode);//同样需要传入字节数组进行解密
  12. System.out.println("【解密后的数据】" + new String(decode));
  13. }

2、自定义数据加密的工具类

Base64并不属于私人的加密处理,而是属于一中在整个互联网上最为常见的一中数据的编码形式,所以如果现在纯粹使用以上的模式基本上是没有加密的意义的,如果要让这些数据存在加密的意义,最佳的做法一定是执行多次的加密处理,同时为了保证数据更加安全,一般还建议在数据前追加一个盐值(salt)。

范例: 自定义数据加密的工具类

  1. /**
  2. * 密码加密工具类
  3. */
  4. public class PasswordUtil {
  5. private static final int REPEAT = 5; // 表示重复加密5次
  6. private static final String SALT = "www.baidu.com";// 追加操作盐值(真正应用的时候盐值要使用随机生成的字符串)
  7. private PasswordUtil(){}//该类的方法为static方法
  8. /**
  9. * 加密的方法
  10. * @param password 需要加密的字符串
  11. * @return 加密后的字符串
  12. */
  13. public static String encrypt(String password){
  14. String encodeData = "{"+ SALT +"}" + password;
  15. Base64.Encoder encoder = Base64.getEncoder();//获得加密类对象
  16. for (int i = 0; i < REPEAT; i++) {
  17. encodeData = encoder.encodeToString(encodeData.getBytes());//执行加密操作
  18. }
  19. return encodeData;
  20. }
  21. /**
  22. * 解密的方法
  23. * @param password 加密后的字符串
  24. * @return 原始字符串数据
  25. */
  26. public static String decrypt(String password){
  27. Base64.Decoder decoder = Base64.getDecoder();//获得解密类对象
  28. byte[] bytes = password.getBytes();//根据字节数组进行解密操作
  29. for (int i = 0; i < REPEAT; i++) {
  30. bytes = decoder.decode(bytes);//多次解密
  31. }
  32. String decodeData = new String(bytes);
  33. return decodeData.substring(("{"+ SALT +"}").length());
  34. }
  35. }

三、RSA非对称加密

1、秘钥生成工具类

  1. /**
  2. * 非对称加密:
  3. * 用公钥加密,用私钥解密,并且公钥加密后的数据无法再用公钥解密
  4. * 生成两把密钥:公钥和私钥
  5. * 公钥用于加密,私钥用于解密
  6. */
  7. public class RSAKeyCreater {
  8. /**
  9. * 注意:
  10. * 1、生成公钥和私钥
  11. * 2、公钥和私钥应该一起生成,否则加密后无法正确解密
  12. * 3、每次调用此方法生成的公钥和私钥都不相同
  13. * @return 公钥和私钥的集合
  14. */
  15. public static Map<String, Object> createKeyPairs() {
  16. Map<String,Object> map = new HashMap<>(2);
  17. try {
  18. Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
  19. KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
  20. generator.initialize(512, new SecureRandom());
  21. KeyPair pair = generator.generateKeyPair();
  22. PublicKey pubKey = pair.getPublic();
  23. PrivateKey privKey = pair.getPrivate();
  24. map.put("publicKey",pubKey);
  25. map.put("privateKey",privKey);
  26. } catch (Exception e) {
  27. e.printStackTrace();
  28. }
  29. return map;
  30. }
  31. }

2、加密解密工具类

  1. /**
  2. * RSA加密解密类
  3. */
  4. public class RsaUtil {
  5. /**
  6. * RSA加密
  7. * @param data 待加密数据
  8. * @param publicKey 公钥
  9. * @return 加密后的数据
  10. */
  11. public static String encryptData(String data, PublicKey publicKey) {
  12. try {
  13. Cipher cipher = Cipher.getInstance("RSA");
  14. cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  15. byte[] dataToEncrypt = data.getBytes("utf-8");
  16. byte[] encryptedData = cipher.doFinal(dataToEncrypt);
  17. String encryptString = Base64.encodeBase64String(encryptedData);
  18. return encryptString;
  19. } catch (Exception e) {
  20. e.printStackTrace();
  21. }
  22. return null;
  23. }
  24. /**
  25. * RSA解密
  26. * @param data 待解密数据
  27. * @param privateKey 私钥
  28. * @return 解密后的数据
  29. */
  30. public static String decryptData(String data, PrivateKey privateKey) {
  31. try {
  32. Cipher cipher = Cipher.getInstance("RSA");
  33. cipher.init(Cipher.DECRYPT_MODE, privateKey);
  34. byte[] descryptData = Base64.decodeBase64(data);
  35. byte[] descryptedData = cipher.doFinal(descryptData);
  36. String srcData = new String(descryptedData, "utf-8");
  37. return srcData;
  38. } catch (Exception e) {
  39. e.printStackTrace();
  40. }
  41. return null;
  42. }
  43. }

四、MD5

  1. /**
  2. * MD5加密---不可逆
  3. */
  4. public class MD5Utils {
  5. /**
  6. * 生成含有随机盐的密码
  7. * @param password 要加密的密码
  8. * @return String 加密后的含有随机盐的密码
  9. */
  10. public static String getSaltMD5(String password) {
  11. // 生成一个16位的随机数
  12. Random random = new Random();
  13. StringBuilder sBuilder = new StringBuilder(16);
  14. sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
  15. int len = sBuilder.length();
  16. if (len < 16) {
  17. for (int i = 0; i < 16 - len; i++) {
  18. sBuilder.append("0");
  19. }
  20. }
  21. // 生成最终的加密盐值
  22. String salt = sBuilder.toString();
  23. password = md5Hex(password + salt);
  24. char[] cs = new char[48];
  25. for (int i = 0; i < 48; i += 3) {
  26. cs[i] = password.charAt(i / 3 * 2);
  27. char c = salt.charAt(i / 3);
  28. cs[i + 1] = c;
  29. cs[i + 2] = password.charAt(i / 3 * 2 + 1);
  30. }
  31. return String.valueOf(cs);
  32. }
  33. /**
  34. * 验证加盐后是否和原密码一致
  35. * @param password 原密码
  36. * @param password 加密之后的密码
  37. * @return boolean true表示和原密码一致 false表示和原密码不一致
  38. */
  39. public static boolean getSaltverifyMD5(String password, String md5str) {
  40. char[] cs1 = new char[32];
  41. char[] cs2 = new char[16];
  42. for (int i = 0; i < 48; i += 3) {
  43. cs1[i / 3 * 2] = md5str.charAt(i);
  44. cs1[i / 3 * 2 + 1] = md5str.charAt(i + 2);
  45. cs2[i / 3] = md5str.charAt(i + 1);
  46. }
  47. String Salt = new String(cs2);
  48. return md5Hex(password + Salt).equals(String.valueOf(cs1));
  49. }
  50. /**
  51. * byte[]字节数组 转换成 十六进制字符串
  52. * @param arr 要转换的byte[]字节数组
  53. * @return String 返回十六进制字符串
  54. */
  55. private static String hex(byte[] arr) {
  56. StringBuilder sb = new StringBuilder();
  57. for (int i = 0; i < arr.length; ++i) {
  58. sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1, 3));
  59. }
  60. return sb.toString();
  61. }
  62. /**
  63. * MD5加密,并把结果由字节数组转换成十六进制字符串
  64. * @param str 要加密的内容
  65. * @return String 返回加密后的十六进制字符串
  66. */
  67. private static String md5Hex(String str) {
  68. try {
  69. MessageDigest md = MessageDigest.getInstance("MD5");
  70. byte[] digest = md.digest(str.getBytes());
  71. return hex(digest);
  72. } catch (Exception e) {
  73. e.printStackTrace();
  74. }
  75. return "";
  76. }
  77. /**
  78. * 测试
  79. * @param args
  80. */
  81. public static void main(String[] args) {
  82. // 原密码
  83. String plaintext = "admin";
  84. // 获取加盐后的MD5值
  85. String ciphertext = MD5Utils.getSaltMD5(plaintext);
  86. System.out.println("加盐后MD5:" + ciphertext);
  87. System.out.println("是否是同一字符串:" + MD5Utils.getSaltverifyMD5(plaintext, ciphertext));
  88. }
  89. }