RSA算法是一种非对称加密算法,所谓非对称就是该算法需要一对密钥,若使用其中一个加密,则需要用另一个才能解密。目前它是最有影响力和最常用的公钥加密算法,能够抵抗已知的绝大多数密码攻击。从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。
    该算法基于一个的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。由于进行的都是大数计算,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. }