1.BASE64加密/解密

Base64 编码是我们程序开发中经常使用到的编码方法,它用 64 个可打印字符来表示二进制数据。这 64 个字符是:小写字母 a-z、大写字母 A-Z、数字 0-9、符号”+”、”/“(再加上作为垫字的”=”,实际上是 65 个字符),其他所有符号都转换成这个字符集中的字符。Base64 编码通常用作存储、传输一些二进制数据编码方法,所以说它本质上是一种将二进制数据转成文本数据的方案。

  1. 通常用作对二进制数据进行加密,示例:
  1. import sun.misc.BASE64Decoder;
  2. import sun.misc.BASE64Encoder;
  3. public class Base64Util {
  4. /***
  5. * BASE64解密
  6. * @param key
  7. * @return
  8. * @throws Exception
  9. */
  10. public static byte[] decryBASE64(String key) throws Exception{
  11. return (new BASE64Decoder()).decodeBuffer(key);
  12. }
  13. /***
  14. * BASE64加密
  15. * @param key
  16. * @return
  17. * @throws Exception
  18. */
  19. public static String encryptBASE64(byte[] key) throws Exception{
  20. return (new BASE64Encoder()).encode(key);
  21. }
  22. }

2.MD5(Message Digest Algorithm)加密

MD5 是将任意长度的数据字符串转化成短小的固定长度的值的单向操作,任意两个字符串不应有相同的散列值。因此 MD5 经常用于校验字符串或者文件,因为如果文件的 MD5 不一样,说明文件内容也是不一样的,如果发现下载的文件和给定的 MD5 值不一样,就要慎重使用。

  1. MD5 主要用做数据一致性验证、数字签名和安全访问认证,而不是用作加密。比如说用户在某个网站注册账户时,输入的密码一般经过 MD5 编码,更安全的做法还会加一层盐(salt),这样密码就具有不可逆性。然后把编码后的密码存入数据库,下次登录的时候把密码 MD5 编码,然后和数据库中的作对比,这样就提升了用户账户的安全性。
  2. 是一种单向加密算法,只能加密不能解密,示例:
  1. import java.security.MessageDigest;
  2. public class MD5Util {
  3. public static final String KEY_MD5 = "MD5";
  4. /***
  5. * MD5加密(生成唯一的MD5值)
  6. * @param data
  7. * @return
  8. * @throws Exception
  9. */
  10. public static byte[] encryMD5(byte[] data) throws Exception {
  11. MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
  12. md5.update(data);
  13. return md5.digest();
  14. }
  15. }

3.DES(Data Encryption Standard)对称加密/解密

DES 是一种对称加密算法,所谓对称加密算法就是:加密和解密使用相同密钥的算法。DES 加密算法出自 IBM 的研究,后来被美国政府正式采用,之后开始广泛流传。但近些年使用越来越少,因为 DES 使用 56 位密钥,以现代的计算能力,24 小时内即可被破解。

  1. 顺便说一下 3DESTriple DES),它是 DES AES 过渡的加密算法,使用 3 56 位的密钥对数据进行三次加密。是 DES 的一个更安全的变形。它以 DES 为基本模块,通过组合分组方法设计出分组加密算法。比起最初的 DES3DES 更为安全。
  2. 使用 Java 实现 DES 加密解密,注意密码长度要是 8 的倍数。加密和解密的 Cipher 构造参数一定要相同,不然会报错。
  3. 数据加密标准算法,和BASE64最明显的区别就是有一个工作密钥,该密钥既用于加密、也用于解密,并且要求密钥是一个长度至少大于8位的字符串,示例:
  1. import java.security.Key;
  2. import java.security.SecureRandom;
  3. import javax.crypto.Cipher;
  4. import javax.crypto.KeyGenerator;
  5. import sun.misc.BASE64Decoder;
  6. import sun.misc.BASE64Encoder;
  7. public class DesUtil {
  8. private static Key key;
  9. private static String KEY_STR="myKey";
  10. private static String CHARSETNAME="UTF-8";
  11. private static String ALGORITHM="DES";
  12. static {
  13. try {
  14. //生成DES算法对象
  15. KeyGenerator generator=KeyGenerator.getInstance(ALGORITHM);
  16. //运用SHA1安全策略
  17. SecureRandom secureRandom=SecureRandom.getInstance("SHA1PRNG");
  18. //设置上密钥种子
  19. secureRandom.setSeed(KEY_STR.getBytes());
  20. //初始化基于SHA1的算法对象
  21. generator.init(secureRandom);
  22. //生成密钥对象
  23. key=generator.generateKey();
  24. generator=null;
  25. } catch (Exception e) {
  26. throw new RuntimeException(e);
  27. }
  28. }
  29. /***
  30. * 获取加密的信息
  31. * @param str
  32. * @return
  33. */
  34. public static String getEncryptString(String str) {
  35. //基于BASE64编码,接收byte[]并转换成String
  36. BASE64Encoder encoder = new BASE64Encoder();
  37. try {
  38. //按utf8编码
  39. byte[] bytes = str.getBytes(CHARSETNAME);
  40. //获取加密对象
  41. Cipher cipher = Cipher.getInstance(ALGORITHM);
  42. //初始化密码信息
  43. cipher.init(Cipher.ENCRYPT_MODE, key);
  44. //加密
  45. byte[] doFinal = cipher.doFinal(bytes);
  46. //byte[]to encode好的String 并返回
  47. return encoder.encode(doFinal);
  48. } catch (Exception e) {
  49. throw new RuntimeException(e);
  50. }
  51. }
  52. /***
  53. * 获取解密之后的信息
  54. * @param str
  55. * @return
  56. */
  57. public static String getDecryptString(String str) {
  58. BASE64Decoder decoder = new BASE64Decoder();
  59. try {
  60. //将字符串decode成byte[]
  61. byte[] bytes = decoder.decodeBuffer(str);
  62. //获取解密对象
  63. Cipher cipher = Cipher.getInstance(ALGORITHM);
  64. //初始化解密信息
  65. cipher.init(Cipher.DECRYPT_MODE, key);
  66. //解密
  67. byte[] doFial = cipher.doFinal(bytes);
  68. return new String(doFial, CHARSETNAME);
  69. } catch (Exception e) {
  70. throw new RuntimeException(e);
  71. }
  72. }
  73. }

4.AES(Advanced Encryption Standard) 加密/解密

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称 Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的 DES,已经被多方分析且广为全世界所使用。简单说就是 DES 的增强版,比 DES 的加密强度更高。

  1. AES DES 一样,一共有四种加密模式:电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)。关于加密模式的介绍,推荐这篇文章:高级加密标准AES的工作模式(ECBCBCCFBOFB),示例代码:
  1. import javax.crypto.Cipher;
  2. import javax.crypto.spec.IvParameterSpec;
  3. import javax.crypto.spec.SecretKeySpec;
  4. public class AESUtil {
  5. public static final String algorithm = "AES";
  6. // AES/CBC/NOPaddin
  7. // AES 默认模式
  8. // 使用CBC模式, 在初始化Cipher对象时, 需要增加参数, 初始化向量IV : IvParameterSpec iv = new
  9. // IvParameterSpec(key.getBytes());
  10. // NOPadding: 使用NOPadding模式时, 原文长度必须是8byte的整数倍
  11. public static final String transformation = "AES/CBC/NOPadding";
  12. public static final String key = "1234567812345678";
  13. /***
  14. * 加密
  15. * @param original 需要加密的参数(注意必须是16位)
  16. * @return
  17. * @throws Exception
  18. */
  19. public static String encryptByAES(String original) throws Exception {
  20. // 获取Cipher
  21. Cipher cipher = Cipher.getInstance(transformation);
  22. // 生成密钥
  23. SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), algorithm);
  24. // 指定模式(加密)和密钥
  25. // 创建初始化向量
  26. IvParameterSpec iv = new IvParameterSpec(key.getBytes());
  27. cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
  28. // cipher.init(Cipher.ENCRYPT_MODE, keySpec);
  29. // 加密
  30. byte[] bytes = cipher.doFinal(original.getBytes());
  31. return Base64Util.encryptBASE64(bytes);
  32. }
  33. /**
  34. * 解密
  35. * @param encrypted 需要解密的参数
  36. * @return
  37. * @throws Exception
  38. */
  39. public static String decryptByAES(String encrypted) throws Exception {
  40. // 获取Cipher
  41. Cipher cipher = Cipher.getInstance(transformation);
  42. // 生成密钥
  43. SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), algorithm);
  44. // 指定模式(解密)和密钥
  45. // 创建初始化向量
  46. IvParameterSpec iv = new IvParameterSpec(key.getBytes());
  47. cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
  48. // cipher.init(Cipher.DECRYPT_MODE, keySpec);
  49. // 解密
  50. byte[] bytes = cipher.doFinal(Base64Util.decryBASE64(encrypted));
  51. return new String(bytes);
  52. }
  53. }

5.HMAC(Hash Message Authentication Code,散列消息鉴别码)

使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证,示例:

  1. import javax.crypto.KeyGenerator;
  2. import javax.crypto.Mac;
  3. import javax.crypto.SecretKey;
  4. import javax.crypto.spec.SecretKeySpec;
  5. public class HMACUtil {
  6. public static final String KEY_MAC = "HmacMD5";
  7. /***
  8. * 初始化HMAC密钥
  9. * @return
  10. * @throws Exception
  11. */
  12. public static String initMacKey() throws Exception{
  13. KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
  14. SecretKey secreKey = keyGenerator.generateKey();
  15. return Base64Util.encryptBASE64(secreKey.getEncoded());
  16. }
  17. /**
  18. * HMAC加密
  19. * @param data
  20. * @param key
  21. * @return
  22. * @throws Exception
  23. */
  24. public static byte[] encryHMAC(byte[] data, String key) throws Exception{
  25. SecretKey secreKey = new SecretKeySpec(Base64Util.decryBASE64(key), KEY_MAC);
  26. Mac mac = Mac.getInstance(secreKey.getAlgorithm());
  27. mac.init(secreKey);
  28. return mac.doFinal();
  29. }
  30. }

6.恺撒加密

  • 在密码学中,恺撒密码是一种最简单并且最广为人知的加密技术。
  • 它是一种替换加密的技术,明文中的所欲字母都在字母表上向后(或向前)按照一个固定的数目进行偏移后被替换成密文。
  • 例如:当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。
  • 这个加密方法是以恺撒的名字命名的,当年恺撒曾用此方法与其将军们进行联系。
  • 恺撒密码通常被座位其他更复杂的加密方法中的一个步骤。

image.png
示例代码:

  1. public class KaisaUtil {
  2. /***
  3. * 使用凯撒加密方式加密数据
  4. * @param orignal 原文
  5. * @param key 密钥
  6. * @return 加密后的字符
  7. */
  8. private static String encryptKaisa(String orignal, int key) {
  9. //将字符串转换为数组
  10. char[] chars = orignal.toCharArray();
  11. StringBuffer buffer = new StringBuffer();
  12. //遍历数组
  13. for(char aChar : chars) {
  14. //获取字符的ASCII编码
  15. int asciiCode = aChar;
  16. //偏移数据
  17. asciiCode += key;
  18. //将偏移后的数据转为字符
  19. char result = (char)asciiCode;
  20. //拼接数据
  21. buffer.append(result);
  22. }
  23. return buffer.toString();
  24. }
  25. /**
  26. * 使用凯撒加密方式解密数据
  27. *
  28. * @param encryptedData :密文
  29. * @param key :密钥
  30. * @return : 源数据
  31. */
  32. private static String decryptKaiser(String encryptedData, int key) {
  33. // 将字符串转为字符数组
  34. char[] chars = encryptedData.toCharArray();
  35. StringBuilder sb = new StringBuilder();
  36. // 遍历数组
  37. for (char aChar : chars) {
  38. // 获取字符的ASCII编码
  39. int asciiCode = aChar;
  40. // 偏移数据
  41. asciiCode -= key;
  42. // 将偏移后的数据转为字符
  43. char result = (char) asciiCode;
  44. // 拼接数据
  45. sb.append(result);
  46. }
  47. return sb.toString();
  48. }
  49. public static void main(String[] args) {
  50. String str = "open fire";
  51. String encode = encryptKaisa(str, 3);
  52. System.out.println("加密后:"+encode);
  53. String decode = decryptKaiser(encode, 3);
  54. System.out.println("解密后:"+decode);
  55. }
  56. }

7.SHA(Secure Hash Algorithm,安全散列算法)

SHA全名叫做安全散列算法,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。

  1. 数字签名等密码学应用中重要的工具,被广泛地应用于电子商务等信息安全领域,示例:
  1. import java.security.MessageDigest;
  2. public class SHAUtil {
  3. public static final String KEY_SHA = "SHA";
  4. public static final String ALGORITHM = "SHA-256";
  5. /***
  6. * SHA加密(比MD5更安全)
  7. * @param data
  8. * @return
  9. * @throws Exception
  10. */
  11. public static byte[] encryptSHA(byte[] data) throws Exception{
  12. MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
  13. sha.update(data);
  14. return sha.digest();
  15. }
  16. public static String SHAEncrypt(final String content) {
  17. try {
  18. MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
  19. byte[] sha_byte = sha.digest(content.getBytes());
  20. StringBuffer hexValue = new StringBuffer();
  21. for (byte b : sha_byte) {
  22. //将其中的每个字节转成十六进制字符串:byte类型的数据最高位是符号位,通过和0xff进行与操作,转换为int类型的正整数。
  23. String toHexString = Integer.toHexString(b & 0xff);
  24. hexValue.append(toHexString.length() == 1 ? "0" + toHexString : toHexString);
  25. }
  26. return hexValue.toString();
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }
  30. return "";
  31. }
  32. //SHA-256加密
  33. public static String SHA256Encrypt(String sourceStr) {
  34. MessageDigest md = null;
  35. try {
  36. md = MessageDigest.getInstance(ALGORITHM);
  37. } catch (NoSuchAlgorithmException e) {
  38. e.printStackTrace();
  39. }
  40. if (null != md) {
  41. md.update(sourceStr.getBytes());
  42. String digestStr = getDigestStr(md.digest());
  43. return digestStr;
  44. }
  45. return null;
  46. }
  47. private static String getDigestStr(byte[] origBytes) {
  48. String tempStr = null;
  49. StringBuilder stb = new StringBuilder();
  50. for (int i = 0; i < origBytes.length; i++) {
  51. tempStr = Integer.toHexString(origBytes[i] & 0xff);
  52. if (tempStr.length() == 1) {
  53. stb.append("0");
  54. }
  55. stb.append(tempStr);
  56. }
  57. return stb.toString();
  58. }
  59. }

8.RSA 加密/解密

RSA算法是一种非对称加密算法,所谓非对称就是该算法需要一对密钥,若使用其中一个加密,则需要用另一个才能解密。目前它是最有影响力和最常用的公钥加密算法,能够抵抗已知的绝大多数密码攻击。从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。

  1. 该算法基于一个的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。由于进行的都是大数计算,RSA 最快的情况也比 DES 慢上好几倍,比对应同样安全级别的对称密码算法要慢 1000 倍左右。所以 RSA 一般只用于少量数据加密,比如说交换对称加密的密钥。

使用 RSA 加密主要有这么几步:生成密钥对、公开公钥、公钥加密私钥解密、私钥加密公钥解密。

示例代码:

  1. import com.sun.org.apache.xml.internal.security.utils.Base64;
  2. import javax.crypto.Cipher;
  3. import org.apache.commons.io.FileUtils;
  4. import java.io.ByteArrayOutputStream;
  5. import java.io.File;
  6. import java.nio.charset.Charset;
  7. import java.security.*;
  8. import java.security.spec.PKCS8EncodedKeySpec;
  9. import java.security.spec.X509EncodedKeySpec;
  10. public class RsaUtil {
  11. /**
  12. * 生成密钥对并保存在本地文件中
  13. *
  14. * @param algorithm : 算法
  15. * @param pubPath : 公钥保存路径
  16. * @param priPath : 私钥保存路径
  17. * @throws Exception
  18. */
  19. private static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception {
  20. // 获取密钥对生成器
  21. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
  22. // 获取密钥对
  23. KeyPair keyPair = keyPairGenerator.generateKeyPair();
  24. // 获取公钥
  25. PublicKey publicKey = keyPair.getPublic();
  26. // 获取私钥
  27. PrivateKey privateKey = keyPair.getPrivate();
  28. // 获取byte数组
  29. byte[] publicKeyEncoded = publicKey.getEncoded();
  30. byte[] privateKeyEncoded = privateKey.getEncoded();
  31. // 进行Base64编码
  32. String publicKeyString = Base64.encode(publicKeyEncoded);
  33. String privateKeyString = Base64.encode(privateKeyEncoded);
  34. // 保存文件
  35. FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8"));
  36. FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8"));
  37. }
  38. /**
  39. * 从文件中加载公钥
  40. *
  41. * @param algorithm : 算法
  42. * @param filePath : 文件路径
  43. * @return : 公钥
  44. * @throws Exception
  45. */
  46. private static PublicKey loadPublicKeyFromFile(String algorithm, String filePath) throws Exception {
  47. // 将文件内容转为字符串
  48. String keyString = FileUtils.readFileToString(new File(filePath), Charset.forName("UTF-8"));
  49. return loadPublicKeyFromString(algorithm, keyString);
  50. }
  51. /**
  52. * 从字符串中加载公钥
  53. *
  54. * @param algorithm : 算法
  55. * @param keyString : 公钥字符串
  56. * @return : 公钥
  57. * @throws Exception
  58. */
  59. private static PublicKey loadPublicKeyFromString(String algorithm, String keyString) throws Exception {
  60. // 进行Base64解码
  61. byte[] decode = Base64.decode(keyString);
  62. // 获取密钥工厂
  63. KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
  64. // 构建密钥规范
  65. X509EncodedKeySpec keyspec = new X509EncodedKeySpec(decode);
  66. // 获取公钥
  67. return keyFactory.generatePublic(keyspec);
  68. }
  69. /**
  70. * 从文件中加载私钥
  71. *
  72. * @param algorithm : 算法
  73. * @param filePath : 文件路径
  74. * @return : 私钥
  75. * @throws Exception
  76. */
  77. private static PrivateKey loadPrivateKeyFromFile(String algorithm, String filePath) throws Exception {
  78. // 将文件内容转为字符串
  79. String keyString = FileUtils.readFileToString(new File(filePath), Charset.forName("UTF-8"));
  80. return loadPrivateKeyFromString(algorithm, keyString);
  81. }
  82. /**
  83. * 从字符串中加载私钥
  84. *
  85. * @param algorithm : 算法
  86. * @param keyString : 私钥字符串
  87. * @return : 私钥
  88. * @throws Exception
  89. */
  90. private static PrivateKey loadPrivateKeyFromString(String algorithm, String keyString) throws Exception {
  91. // 进行Base64解码
  92. byte[] decode = Base64.decode(keyString);
  93. // 获取密钥工厂
  94. KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
  95. // 构建密钥规范
  96. PKCS8EncodedKeySpec keyspec = new PKCS8EncodedKeySpec(decode);
  97. // 生成私钥
  98. return keyFactory.generatePrivate(keyspec);
  99. }
  100. /**
  101. * 使用密钥加密数据
  102. *
  103. * @param algorithm : 算法
  104. * @param input : 原文
  105. * @param key : 密钥
  106. * @param maxEncryptSize : 最大加密长度(需要根据实际情况进行调整)
  107. * @return : 密文
  108. * @throws Exception
  109. */
  110. private static String encrypt(String algorithm, String input, Key key, int maxEncryptSize) throws Exception {
  111. // 获取Cipher对象
  112. Cipher cipher = Cipher.getInstance(algorithm);
  113. // 初始化模式(加密)和密钥
  114. cipher.init(Cipher.ENCRYPT_MODE, key);
  115. // 将原文转为byte数组
  116. byte[] data = input.getBytes();
  117. // 总数据长度
  118. int total = data.length;
  119. // 输出流
  120. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  121. decodeByte(maxEncryptSize, cipher, data, total, baos);
  122. // 对密文进行Base64编码
  123. return Base64.encode(baos.toByteArray());
  124. }
  125. /**
  126. * 解密数据
  127. *
  128. * @param algorithm : 算法
  129. * @param encrypted : 密文
  130. * @param key : 密钥
  131. * @param maxDecryptSize : 最大解密长度(需要根据实际情况进行调整)
  132. * @return : 原文
  133. * @throws Exception
  134. */
  135. private static String decrypt(String algorithm, String encrypted, Key key, int maxDecryptSize) throws Exception {
  136. // 获取Cipher对象
  137. Cipher cipher = Cipher.getInstance(algorithm);
  138. // 初始化模式(解密)和密钥
  139. cipher.init(Cipher.DECRYPT_MODE, key);
  140. // 由于密文进行了Base64编码, 在这里需要进行解码
  141. byte[] data = Base64.decode(encrypted);
  142. // 总数据长度
  143. int total = data.length;
  144. // 输出流
  145. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  146. decodeByte(maxDecryptSize, cipher, data, total, baos);
  147. // 输出原文
  148. return baos.toString();
  149. }
  150. /**
  151. * 分段处理数据
  152. *
  153. * @param maxSize : 最大处理能力
  154. * @param cipher : Cipher对象
  155. * @param data : 要处理的byte数组
  156. * @param total : 总数据长度
  157. * @param baos : 输出流
  158. * @throws Exception
  159. */
  160. private static void decodeByte(int maxSize, Cipher cipher, byte[] data, int total, ByteArrayOutputStream baos) throws Exception {
  161. // 偏移量
  162. int offset = 0;
  163. // 缓冲区
  164. byte[] buffer;
  165. // 如果数据没有处理完, 就一直继续
  166. while (total - offset > 0) {
  167. // 如果剩余的数据 >= 最大处理能力, 就按照最大处理能力来加密数据
  168. if (total - offset >= maxSize) {
  169. // 加密数据
  170. buffer = cipher.doFinal(data, offset, maxSize);
  171. // 偏移量向右侧偏移最大数据能力个
  172. offset += maxSize;
  173. } else {
  174. // 如果剩余的数据 < 最大处理能力, 就按照剩余的个数来加密数据
  175. buffer = cipher.doFinal(data, offset, total - offset);
  176. // 偏移量设置为总数据长度, 这样可以跳出循环
  177. offset = total;
  178. }
  179. // 向输出流写入数据
  180. baos.write(buffer);
  181. }
  182. }
  183. }

加密算法的安全级别(Security Level of Cryptographic Algorithms):

安全级别
(Security Level)
工作因素
(Work Factor)
算法
(Algorithms)
薄弱(Weak) O(240) DES, MD5
传统(Legacy) O(264) RC4, SHA-1
基准(Baseline) O(280) 3DES
标准(Standard) O(2128) AES-128, SHA-256
较高(High) O(2192) AES-192, SHA-384
超高(Ultra) O(2256) AES-256, SHA-512

9.PBE 加密/解密

PBE是一种基于口令的加密算法,使用口令代替其他对称加密算法中的密钥,其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法保证数据的安全性。

  1. PBE算法是对称加密算法的综合算法,常见算法PBEWithMD5AndDES,使用MD5DES算法构建了PBE算法。将盐附加在口令上,通过消息摘要算法经过迭代获得构建密钥的基本材料,构建密钥后使用对称加密算法进行加密解密。

算法/密钥长度/默认密钥长度:

1.PBEWithMD5AndDES/56/56
2.PBEWithMD5AndTripleDES/112,168/168
3.PBEWithSHA1AndDESede/112,168/168
4.PBEWithSHA1AndRC2_40/40 to 1024/128
工作模式:CBC
填充方式:PKCS5Padding
示例代码:

  1. import java.security.Key;
  2. import java.security.SecureRandom;
  3. import javax.crypto.Cipher;
  4. import javax.crypto.SecretKeyFactory;
  5. import javax.crypto.spec.PBEKeySpec;
  6. import javax.crypto.spec.PBEParameterSpec;
  7. public class PBEUtil {
  8. public static final String ALGORITHM = "PBEWITHMD5andDES";
  9. public static final int ITERATION_COUNT = 100;
  10. public static byte[] initSalt() throws Exception{
  11. //实例化安全随机数
  12. SecureRandom random = new SecureRandom();
  13. return random.generateSeed(8);
  14. }
  15. /***
  16. * 转换密钥
  17. * @param password 密码
  18. * @return 密钥
  19. * @throws Exception
  20. */
  21. private static Key toKey(String password) throws Exception{
  22. //密钥材料
  23. PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
  24. //实例化
  25. SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
  26. //生成密钥
  27. return factory.generateSecret(keySpec);
  28. }
  29. /***
  30. * 加密
  31. * @param data 待加密数据
  32. * @param password 密钥
  33. * @param salt
  34. * @return
  35. * @throws Exception
  36. */
  37. public static byte[] encrypt(byte[] data, String password, byte[] salt) throws Exception{
  38. //转换密钥
  39. Key key = toKey(password);
  40. //实例化PBE参数材料
  41. PBEParameterSpec spec = new PBEParameterSpec(salt, ITERATION_COUNT);
  42. //实例化
  43. Cipher cipher = Cipher.getInstance(ALGORITHM);
  44. //初始化
  45. cipher.init(Cipher.ENCRYPT_MODE, key, spec);
  46. return cipher.doFinal(data);
  47. }
  48. /***
  49. * 解密
  50. * @param data 待解密数据
  51. * @param password 密钥
  52. * @param salt
  53. * @return
  54. * @throws Exception
  55. */
  56. public static byte[] decrypt(byte[] data, String password, byte[] salt) throws Exception{
  57. //转换密钥
  58. Key key = toKey(password);
  59. //实例化PBE参数材料
  60. PBEParameterSpec spec = new PBEParameterSpec(salt, ITERATION_COUNT);
  61. //实例化
  62. Cipher cipher = Cipher.getInstance(ALGORITHM);
  63. //初始化
  64. cipher.init(Cipher.DECRYPT_MODE, key, spec);
  65. //执行操作
  66. return cipher.doFinal(data);
  67. }
  68. private static String showByteArray(byte[] data) {
  69. if(null == data) {
  70. return null;
  71. }
  72. StringBuilder sb = new StringBuilder();
  73. for(byte b : data) {
  74. sb.append(b).append(",");
  75. }
  76. sb.deleteCharAt(sb.length()-1);
  77. sb.append("");
  78. return sb.toString();
  79. }
  80. public static void main(String[] args) throws Exception{
  81. byte[] salt = initSalt();
  82. System.out.println("salt:"+showByteArray(salt));
  83. String password = "1111";
  84. System.out.println("口令:"+password);
  85. String data = "PBE数据";
  86. System.out.println("加密前数据:String:"+data);
  87. System.out.println("加密前数据:byte[]:"+showByteArray(data.getBytes()));
  88. byte[] encryptData = encrypt(data.getBytes(), password, salt);
  89. System.out.println("加密后数据:byte[]:"+showByteArray(encryptData));
  90. byte[] decryptData = decrypt(encryptData, password, salt);
  91. System.out.println("解密后数据: byte[]:"+showByteArray(decryptData));
  92. System.out.println("解密后数据: string:"+new String(decryptData));
  93. }
  94. }

感谢作者:https://blog.csdn.net/theUncle/article/details/100156976