Java加密解密快速入门上篇【包括MD5、BASE64、DES、RSA等算法】

梦里梦外; 2021-06-10 20:42 402阅读 0赞

搞Java的攻城狮应该比较欣喜若狂的,不仅Sun公司的JDK提供了庞大的类库,而且还有众多的开源组织和个人不断地丰富着Java的生态系统。没错的,诸如MD5、BASE64、DES、RSA等经典加密解密算法,JDK都有提供专门的API来封装相关操作。程序猿只需要了解算法的思想,以及学习如何使用API即可。吻当然,针对BASE64算法,JDK仅仅提供了非常标准的实现,在某些场景下无法满足应用需求。在最后一部分,将学习Apache提供的Commons Codec大笑对BASE64算法的扩展实现,以满足实践的需要。

<一>. MD5加密算法:

  1. 消息摘要算法第五版(Message Digest Algorithm),是一种单向加密算法,只能加密、无法解密。然而MD5加密算法已经被中国山东大学王小云教授成功破译![哭][smiley-cry.gif],但是在安全性要求不高的场景下,MD5加密算法仍然具有应用价值。
  1. 创建md5对象:

Java代码

  1. MessageDigest md5 = MessageDigest.getInstance(“md5”);

    1. 进行加密操作:

Java代码

  1. byte[] cipherData = md5.digest(plainText.getBytes());

    1. 将其中的每个字节转成十六进制字符串:byte类型的数据最高位是符号位,通过和0xff进行与操作,转换为int类型的正整数。

Java代码

  1. String toHexStr = Integer.toHexString(cipher & 0xff);

    1. 如果该正数小于16(长度为1个字符),前面拼接0占位:确保最后生成的是32位字符串。

Java代码

  1. builder.append(toHexStr.length() == 1 ? “0” + toHexStr : toHexStr);

    1. 加密转换之后的字符串为:c0bb4f54f1d8b14caf6fe1069e5f93ad

    2. 完整的MD5算法应用如下所示:

Java代码

  1. /**
  2. * 功能简述: 测试MD5单向加密.
  3. * @throws Exception
  4. */
  5. @Test
  6. public void test01() throws Exception {
  7. String plainText = “Hello , world !”;
  8. MessageDigest md5 = MessageDigest.getInstance(“md5”);
  9. byte[] cipherData = md5.digest(plainText.getBytes());
  10. StringBuilder builder = new StringBuilder();
  11. for(byte cipher : cipherData) {
  12. String toHexStr = Integer.toHexString(cipher & 0xff);
  13. builder.append(toHexStr.length() == 1 ? “0” + toHexStr : toHexStr);
  14. }
  15. System.out.println(builder.toString());
  16. //c0bb4f54f1d8b14caf6fe1069e5f93ad
  17. }

<二>. 使用BASE64进行加密/解密:

  1. 使用BASE64算法通常用作对二进制数据进行加密,加密之后的数据不易被肉眼识别。严格来说,经过BASE64加密的数据其实没有安全性可言![保密][smiley-sealed.gif],因为它的加密解密算法都是公开的,典型的防菜鸟不防程序猿的呀。 经过标准的BASE64算法加密后的数据, 通常包含/、+、=等特殊符号,不适合作为url参数传递,幸运的是ApacheCommons Codec模块提供了对BASE64的进一步封装。 (参见最后一部分的说明)
  1. 使用BASE64加密:

Java代码

  1. BASE64Encoder encoder = new BASE64Encoder();
  2. String cipherText = encoder.encode(plainText.getBytes());

    1. 使用BASE64解密:

Java代码

  1. BASE64Decoder decoder = new BASE64Decoder();
  2. plainText = new String(decoder.decodeBuffer(cipherText));

    1. 完整代码示例:

Java代码

  1. /**
  2. * 功能简述: 使用BASE64进行双向加密/解密.
  3. * @throws Exception
  4. */
  5. @Test
  6. public void test02() throws Exception {
  7. BASE64Encoder encoder = new BASE64Encoder();
  8. BASE64Decoder decoder = new BASE64Decoder();
  9. String plainText = “Hello , world !”;
  10. String cipherText = encoder.encode(plainText.getBytes());
  11. System.out.println(“cipherText : “ + cipherText);
  12. //cipherText : SGVsbG8gLCB3b3JsZCAh
  13. System.out.println(“plainText : “ +
  14. new String(decoder.decodeBuffer(cipherText)));
  15. //plainText : Hello , world !

<三>. 使用DES对称加密/解密:

  1. 数据加密标准算法(Data Encryption Standard),和BASE64最明显的区别就是有一个工作密钥,该密钥既用于加密、也用于解密,并且要求密钥是一个长度至少大于8位的字符串。使用DES加密、解密的核心是确保工作密钥的安全性。![叫喊][smiley-yell.gif]
  1. 根据key生成密钥:

Java代码

  1. DESKeySpec keySpec = new DESKeySpec(key.getBytes());
  2. SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(“des”);
  3. SecretKey secretKey = keyFactory.generateSecret(keySpec);

    1. 加密操作:

Java代码

  1. Cipher cipher = Cipher.getInstance(“des”);
  2. cipher.init(Cipher.ENCRYPT_MODE, secretKey, new SecureRandom());
  3. byte[] cipherData = cipher.doFinal(plainText.getBytes());

    1. 为了便于观察生成的加密数据,使用BASE64再次加密:

Java代码

  1. String cipherText = new BASE64Encoder().encode(cipherData);

    生成密文如下:PtRYi3sp7TOR69UrKEIicA==

    1. 解密操作:

Java代码

  1. cipher.init(Cipher.DECRYPT_MODE, secretKey, new SecureRandom());
  2. byte[] plainData = cipher.doFinal(cipherData);
  3. String plainText = new String(plainData);

    1. 完整的代码demo:

Java代码

  1. /**
  2. * 功能简述: 使用DES对称加密/解密.
  3. * @throws Exception
  4. */
  5. @Test
  6. public void test03() throws Exception {
  7. String plainText = “Hello , world !”;
  8. String key = “12345678”; //要求key至少长度为8个字符
  9. SecureRandom random = new SecureRandom();
  10. DESKeySpec keySpec = new DESKeySpec(key.getBytes());
  11. SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(“des”);
  12. SecretKey secretKey = keyFactory.generateSecret(keySpec);
  13. Cipher cipher = Cipher.getInstance(“des”);
  14. cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
  15. byte[] cipherData = cipher.doFinal(plainText.getBytes());
  16. System.out.println(“cipherText : “ + new BASE64Encoder().encode(cipherData));
  17. //PtRYi3sp7TOR69UrKEIicA==
  18. cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
  19. byte[] plainData = cipher.doFinal(cipherData);
  20. System.out.println(“plainText : “ + new String(plainData));
  21. //Hello , world !
  22. }

<四>. 使用RSA非对称加密/解密:

  1. RSA算法是非对称加密算法的典型代表,既能加密、又能解密。和对称加密算法比如DES的明显区别在于用于加密、解密的密钥是不同的。使用RSA算法,只要密钥足够长(一般要求1024bit),加密的信息是不能被破解的。![天真][smiley-innocent.gif]用户通过https协议访问服务器时,就是使用非对称加密算法进行数据的加密、解密操作的。
  2. 服务器发送数据给客户端时使用私钥(private key)进行加密,并且使用加密之后的数据和私钥生成数字签名(digital signature)并发送给客户端。客户端接收到服务器发送的数据会使用公钥(public key)对数据来进行解密,并且根据加密数据和公钥验证数字签名的有效性,防止加密数据在传输过程中被第三方进行了修改。
  3. 客户端发送数据给服务器时使用公钥进行加密,服务器接收到加密数据之后使用私钥进行解密。
  1. 创建密钥对KeyPair:

Java代码

  1. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(“rsa”);
  2. keyPairGenerator.initialize(1024); //密钥长度推荐为1024位.
  3. KeyPair keyPair = keyPairGenerator.generateKeyPair();

    1. 获取公钥/私钥:

Java代码

  1. PublicKey publicKey = keyPair.getPublic();
  2. PrivateKey privateKey = keyPair.getPrivate();

    1. 服务器数据使用私钥加密:

Java代码

  1. Cipher cipher = Cipher.getInstance(“rsa”);
  2. cipher.init(Cipher.ENCRYPT_MODE, privateKey, new SecureRandom());
  3. byte[] cipherData = cipher.doFinal(plainText.getBytes());

    1. 用户使用公钥解密:

Java代码

  1. cipher.init(Cipher.DECRYPT_MODE, publicKey, new SecureRandom());
  2. byte[] plainData = cipher.doFinal(cipherData);

    1. 服务器根据私钥和加密数据生成数字签名:

Java代码

  1. Signature signature = Signature.getInstance(“MD5withRSA”);
  2. signature.initSign(privateKey);
  3. signature.update(cipherData);
  4. byte[] signData = signature.sign();

    1. 用户根据公钥、加密数据验证数据是否被修改过:

Java代码

  1. signature.initVerify(publicKey);
  2. signature.update(cipherData);
  3. boolean status = signature.verify(signData);

    1. RSA算法代码demo:尴尬

Java代码

  1. /**
  2. * 功能简述: 使用RSA非对称加密/解密.
  3. * @throws Exception
  4. */
  5. @Test
  6. public void test04() throws Exception {
  7. String plainText = “Hello , world !”;
  8. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(“rsa”);
  9. keyPairGenerator.initialize(1024);
  10. KeyPair keyPair = keyPairGenerator.generateKeyPair();
  11. PublicKey publicKey = keyPair.getPublic();
  12. PrivateKey privateKey = keyPair.getPrivate();
  13. Cipher cipher = Cipher.getInstance(“rsa”);
  14. SecureRandom random = new SecureRandom();
  15. cipher.init(Cipher.ENCRYPT_MODE, privateKey, random);
  16. byte[] cipherData = cipher.doFinal(plainText.getBytes());
  17. System.out.println(“cipherText : “ + new BASE64Encoder().encode(cipherData));
  18. //gDsJxZM98U2GzHUtUTyZ/Ir/NXqRWKUJkl6olrLYCZHY3RnlF3olkWPZ35Dwz9BMRqaTL3oPuyVq
  19. //sehvHExxj9RyrWpIYnYLBSURB1KVUSLMsd/ONFOD0fnJoGtIk+T/+3yybVL8M+RI+HzbE/jdYa/+
  20. //yQ+vHwHqXhuzZ/N8iNg=
  21. cipher.init(Cipher.DECRYPT_MODE, publicKey, random);
  22. byte[] plainData = cipher.doFinal(cipherData);
  23. System.out.println(“plainText : “ + new String(plainData));
  24. //Hello , world !
  25. Signature signature = Signature.getInstance(“MD5withRSA”);
  26. signature.initSign(privateKey);
  27. signature.update(cipherData);
  28. byte[] signData = signature.sign();
  29. System.out.println(“signature : “ + new BASE64Encoder().encode(signData));
  30. //ADfoeKQn6eEHgLF8ETMXan3TfFO03R5u+cQEWtAQ2lRblLZw1DpzTlJJt1RXjU451I84v3297LhR
  31. //co64p6Sq3kVt84wnRsQw5mucZnY+jRZNdXpcbwh2qsh8287NM2hxWqp4OOCf/+vKKXZ3pbJMNT/4
  32. ///t9ewo+KYCWKOgvu5QQ=
  33. signature.initVerify(publicKey);
  34. signature.update(cipherData);
  35. boolean status = signature.verify(signData);
  36. System.out.println(“status : “ + status);
  37. //true
  38. }
  1. Ok,这个blog的内容够长的了,还是在下一篇博客中对加密解密封装成一个工具类吧,然后简单介绍一下Commons CodecBASE64的扩展支持!![微笑][smiley-smile.gif]

发表评论

表情:
评论列表 (有 0 条评论,402人围观)

还没有评论,来说两句吧...

相关阅读