当前位置:   article > 正文

Java,PHP RSA加密解密,分段加解密及RSA签名_rsa2048签名长度

rsa2048签名长度
  1. 对接第三方支付系统接口,为这通信的安全性,通常有MD5签名,RSA签名为主,今天主要讲解RSA加解密及签名。
  2. RSA密钥长度有1024和2048位的,由于RSA加密的特殊性,文本内容过长不进行分段加密的话会出来加密失败
  3. 1024加密长度为:117,解密长度为:128; 2048加密长度为:245,解密长度为:256,这个地方特别需要注意,根据密钥长度修改不同的参数值
  4. 本地生成密钥对工具地址:本地生成RSA密钥对工具包,RSA加密解密-Java文档类资源-CSDN下载

JAVA RSA加解密工具类源码:

  1. package com.pay.utils;
  2. import java.io.ByteArrayOutputStream;
  3. import java.security.Key;
  4. import java.security.KeyFactory;
  5. import java.security.KeyPair;
  6. import java.security.KeyPairGenerator;
  7. import java.security.NoSuchAlgorithmException;
  8. import java.security.interfaces.RSAPrivateKey;
  9. import java.security.interfaces.RSAPublicKey;
  10. import java.security.spec.InvalidKeySpecException;
  11. import java.security.spec.PKCS8EncodedKeySpec;
  12. import java.security.spec.X509EncodedKeySpec;
  13. import java.util.HashMap;
  14. import java.util.Map;
  15. import javax.crypto.Cipher;
  16. public class RSAEncrypt {
  17. /**
  18. * 字节数据转字符串专用集合
  19. */
  20. private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6',
  21. '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  22. /**
  23. * 加密算法RSA
  24. */
  25. public static final String KEY_ALGORITHM = "RSA";
  26. /**
  27. * 公钥
  28. */
  29. public static final String PUBLIC_KEY = "publicKey";
  30. /**
  31. * 私钥
  32. */
  33. public static final String PRIVATE_KEY = "privateKey";
  34. /**
  35. * RSA最大加密明文大小
  36. */
  37. private static final int MAX_ENCRYPT_BLOCK = 245;
  38. /**
  39. * RSA最大解密密文大小
  40. */
  41. private static final int MAX_DECRYPT_BLOCK = 256;
  42. public static Map<String, String> generatorRSAKey(){
  43. //获得对象 KeyPairGenerator 参数 RSA 2048个字节
  44. KeyPairGenerator keyPairGen = null;
  45. try {
  46. keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  47. } catch (NoSuchAlgorithmException e) {
  48. e.printStackTrace();
  49. }
  50. keyPairGen.initialize(2048);
  51. //通过对象 KeyPairGenerator 获取对象KeyPair
  52. KeyPair keyPair = keyPairGen.generateKeyPair();
  53. byte[] publicBytes = keyPair.getPublic().getEncoded();
  54. byte[] privateBytes = keyPair.getPrivate().getEncoded();
  55. //公私钥对象存入map中
  56. Map<String, String> keyMap = new HashMap<String, String>();
  57. keyMap.put(PUBLIC_KEY, Base64.encode(publicBytes));
  58. keyMap.put(PRIVATE_KEY, Base64.encode(privateBytes));
  59. return keyMap;
  60. }
  61. /**
  62. * 从字符串中加载公钥
  63. *
  64. * @param publicKeyStr
  65. * 公钥数据字符串
  66. * @throws Exception
  67. * 加载公钥时产生的异常
  68. */
  69. public static RSAPublicKey getPublicKey(String publicKeyStr)
  70. throws Exception {
  71. try {
  72. byte[] buffer = Base64.decode(publicKeyStr);
  73. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  74. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
  75. return (RSAPublicKey) keyFactory.generatePublic(keySpec);
  76. } catch (NoSuchAlgorithmException e) {
  77. throw new Exception("无此算法");
  78. } catch (InvalidKeySpecException e) {
  79. throw new Exception("公钥非法");
  80. } catch (NullPointerException e) {
  81. throw new Exception("公钥数据为空");
  82. }
  83. }
  84. public static RSAPrivateKey getPrivateKey(String privateKeyStr)
  85. throws Exception {
  86. try {
  87. byte[] buffer = Base64.decode(privateKeyStr);
  88. PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
  89. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  90. return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
  91. } catch (NoSuchAlgorithmException e) {
  92. throw new Exception("无此算法");
  93. } catch (InvalidKeySpecException e) {
  94. throw new Exception("私钥非法");
  95. } catch (NullPointerException e) {
  96. throw new Exception("私钥数据为空");
  97. }
  98. }
  99. /**
  100. * <P>
  101. * 私钥解密
  102. * </p>
  103. *
  104. * @param encryptedData
  105. * 已加密数据
  106. * @param privateKey
  107. * 私钥(BASE64编码)
  108. * @return
  109. * @throws Exception
  110. */
  111. public static String decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {
  112. byte[] keyBytes = Base64.decode(privateKey);
  113. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  114. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  115. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  116. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  117. cipher.init(Cipher.DECRYPT_MODE, privateK);
  118. int inputLen = encryptedData.length;
  119. ByteArrayOutputStream out = new ByteArrayOutputStream();
  120. int offSet = 0;
  121. byte[] cache;
  122. int i = 0;
  123. // 对数据分段解密
  124. while (inputLen - offSet > 0) {
  125. if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  126. cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
  127. } else {
  128. cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
  129. }
  130. out.write(cache, 0, cache.length);
  131. i++;
  132. offSet = i * MAX_DECRYPT_BLOCK;
  133. }
  134. byte[] decryptedData = out.toByteArray();
  135. out.close();
  136. return new String(decryptedData, "UTF-8");
  137. }
  138. /**
  139. * <p>
  140. * 公钥解密
  141. * </p>
  142. *
  143. * @param encryptedData
  144. * 已加密数据
  145. * @param publicKey
  146. * 公钥(BASE64编码)
  147. * @return
  148. * @throws Exception
  149. */
  150. public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception {
  151. byte[] keyBytes = Base64.decode(publicKey);
  152. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  153. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  154. Key publicK = keyFactory.generatePublic(x509KeySpec);
  155. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  156. cipher.init(Cipher.DECRYPT_MODE, publicK);
  157. int inputLen = encryptedData.length;
  158. ByteArrayOutputStream out = new ByteArrayOutputStream();
  159. int offSet = 0;
  160. byte[] cache;
  161. int i = 0;
  162. // 对数据分段解密
  163. while (inputLen - offSet > 0) {
  164. if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  165. cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
  166. } else {
  167. cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
  168. }
  169. out.write(cache, 0, cache.length);
  170. i++;
  171. offSet = i * MAX_DECRYPT_BLOCK;
  172. }
  173. byte[] decryptedData = out.toByteArray();
  174. out.close();
  175. return decryptedData;
  176. }
  177. /**
  178. * <p>
  179. * 公钥加密
  180. * </p>
  181. *
  182. * @param data
  183. * 源数据
  184. * @param publicKey
  185. * 公钥(BASE64编码)
  186. * @return
  187. * @throws Exception
  188. */
  189. public static String encryptByPublicKey(byte[] data, String publicKey) throws Exception {
  190. byte[] keyBytes = Base64.decode(publicKey);
  191. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  192. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  193. Key publicK = keyFactory.generatePublic(x509KeySpec);
  194. // 对数据加密
  195. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  196. cipher.init(Cipher.ENCRYPT_MODE, publicK);
  197. int inputLen = data.length;
  198. ByteArrayOutputStream out = new ByteArrayOutputStream();
  199. int offSet = 0;
  200. byte[] cache;
  201. int i = 0;
  202. // 对数据分段加密
  203. while (inputLen - offSet > 0) {
  204. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  205. cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  206. } else {
  207. cache = cipher.doFinal(data, offSet, inputLen - offSet);
  208. }
  209. out.write(cache, 0, cache.length);
  210. i++;
  211. offSet = i * MAX_ENCRYPT_BLOCK;
  212. }
  213. byte[] encryptedData = out.toByteArray();
  214. out.close();
  215. return Base64.encode(encryptedData);
  216. }
  217. /**
  218. * <p>
  219. * 私钥加密
  220. * </p>
  221. *
  222. * @param data
  223. * 源数�?
  224. * @param privateKey
  225. * 私钥(BASE64编码)
  226. * @return
  227. * @throws Exception
  228. */
  229. public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
  230. byte[] keyBytes = Base64.decode(privateKey);
  231. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  232. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  233. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  234. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  235. cipher.init(Cipher.ENCRYPT_MODE, privateK);
  236. int inputLen = data.length;
  237. ByteArrayOutputStream out = new ByteArrayOutputStream();
  238. int offSet = 0;
  239. byte[] cache;
  240. int i = 0;
  241. // 对数据分段加密
  242. while (inputLen - offSet > 0) {
  243. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  244. cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  245. } else {
  246. cache = cipher.doFinal(data, offSet, inputLen - offSet);
  247. }
  248. out.write(cache, 0, cache.length);
  249. i++;
  250. offSet = i * MAX_ENCRYPT_BLOCK;
  251. }
  252. byte[] encryptedData = out.toByteArray();
  253. out.close();
  254. return encryptedData;
  255. }
  256. /**
  257. * 公钥加密
  258. * @param publicKeyStr
  259. * @param data 加密字符串
  260. * @return String 密文数据
  261. * @throws Exception
  262. */
  263. public static String encryptForPublicKey(String data, String publicKeyStr) throws Exception{
  264. return encryptByPublicKey(data.getBytes(), publicKeyStr);
  265. }
  266. /**
  267. * 私钥加密
  268. * @param privateKeyStr 私钥
  269. * @param data 加密字符串
  270. * @return String 密文数据
  271. * @throws Exception
  272. */
  273. public static String encryptForPrivateKey(String data, String privateKeyStr) throws Exception{
  274. byte[] decryptedData = encryptByPrivateKey(data.getBytes(), privateKeyStr);
  275. return Base64.encode(decryptedData);
  276. }
  277. /**
  278. * 私钥解密方法
  279. * @param privateKey 私钥
  280. * @param plainTextData 密文
  281. * @return String 明文
  282. * @throws Exception
  283. */
  284. public static String decryptForPrivateKey(String plainTextData, String privateKey) throws Exception{
  285. return decryptByPrivateKey(plainTextData.getBytes(), privateKey);
  286. }
  287. /**
  288. * 公钥解密方法
  289. * @param publicKey
  290. * @param plainTextData 密文
  291. * @return 明文
  292. * @throws Exception
  293. */
  294. public static String decryptForPublicKey(String plainTextData, String publicKey) throws Exception{
  295. byte[] decryptedData = decryptByPublicKey(Base64.decode(plainTextData), publicKey);
  296. return new String(decryptedData);
  297. }
  298. /**
  299. * 字节数据转十六进制字符串
  300. *
  301. * @param data
  302. * 输入数据
  303. * @return 十六进制内容
  304. */
  305. public static String byteArrayToString(byte[] data) {
  306. StringBuilder stringBuilder = new StringBuilder();
  307. for (int i = 0; i < data.length; i++) {
  308. // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
  309. stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
  310. // 取出字节的低四位 作为索引得到相应的十六进制标识符
  311. stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
  312. if (i < data.length - 1) {
  313. stringBuilder.append(' ');
  314. }
  315. }
  316. return stringBuilder.toString();
  317. }
  318. static String bytesToString(byte[] encrytpByte) {
  319. String result = "";
  320. for (Byte bytes : encrytpByte) {
  321. result += bytes.toString() + " ";
  322. }
  323. return result;
  324. }
  325. }

RSA签名工具类源码:

  1. package com.pay.utils;
  2. import java.lang.reflect.Field;
  3. import java.security.KeyFactory;
  4. import java.security.PrivateKey;
  5. import java.security.PublicKey;
  6. import java.security.spec.PKCS8EncodedKeySpec;
  7. import java.security.spec.X509EncodedKeySpec;
  8. import java.util.Comparator;
  9. import java.util.HashMap;
  10. import java.util.Map;
  11. public class RSASignature{
  12. /**
  13. * 签名算法
  14. */
  15. public static final String SIGN_ALGORITHMS = "SHA256WithRSA";
  16. /**
  17. * 加密算法RSA
  18. */
  19. public static final String KEY_ALGORITHM = "RSA";
  20. /**
  21. * RSA签名
  22. * @param content 待签名数据
  23. * @param privateKey 商户私钥
  24. * @param encode 字符集编码
  25. * @return 签名值
  26. */
  27. public static String sign(String content, String privateKey, String encode)
  28. {
  29. try
  30. {
  31. PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
  32. KeyFactory keyf = KeyFactory.getInstance(KEY_ALGORITHM);
  33. PrivateKey priKey = keyf.generatePrivate(priPKCS8);
  34. java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
  35. signature.initSign(priKey);
  36. signature.update(content.getBytes(encode));
  37. byte[] signed = signature.sign();
  38. return Base64.encode(signed);
  39. }
  40. catch (Exception e)
  41. {
  42. e.printStackTrace();
  43. }
  44. return null;
  45. }
  46. /**
  47. * 根据 content 和 私钥 生成签名
  48. * @param content 按字典顺序排序的内容
  49. * @param privateKey ftp上保存的私钥
  50. * @return
  51. */
  52. public static String sign(String content, String privateKey)
  53. {
  54. try
  55. {
  56. PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec( Base64.decode(privateKey) );
  57. KeyFactory keyf = KeyFactory.getInstance(KEY_ALGORITHM);
  58. PrivateKey priKey = keyf.generatePrivate(priPKCS8);
  59. java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
  60. signature.initSign(priKey);
  61. signature.update(content.getBytes());
  62. byte[] signed = signature.sign();
  63. return Base64.encode(signed);
  64. }
  65. catch (Exception e)
  66. {
  67. e.printStackTrace();
  68. }
  69. return null;
  70. }
  71. /**
  72. * RSA验签名检查
  73. * @param content 待签名数据
  74. * @param sign 签名值
  75. * @param publicKey 分配给开发商公钥
  76. * @param encode 字符集编码
  77. * @return 布尔值
  78. */
  79. public static boolean doCheck(String content, String sign, String publicKey,String encode)
  80. {
  81. try
  82. {
  83. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  84. byte[] encodedKey = Base64.decode(publicKey);
  85. PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
  86. java.security.Signature signature = java.security.Signature
  87. .getInstance(SIGN_ALGORITHMS);
  88. signature.initVerify(pubKey);
  89. signature.update( content.getBytes(encode) );
  90. boolean bverify = signature.verify( Base64.decode(sign) );
  91. return bverify;
  92. }
  93. catch (Exception e)
  94. {
  95. e.printStackTrace();
  96. }
  97. return false;
  98. }
  99. /**
  100. * RSA验签名检查
  101. * @param content 待签名数据
  102. * @param sign 签名值
  103. * @param publicKey 分配给开发商公钥
  104. * @return 布尔值
  105. */
  106. public static boolean doCheck(String content, String sign, String publicKey)
  107. {
  108. try
  109. {
  110. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  111. byte[] encodedKey = Base64.decode(publicKey);
  112. if (encodedKey==null){
  113. return false;
  114. }
  115. PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
  116. // 用私钥对信息生成数字签名
  117. java.security.Signature signature = java.security.Signature
  118. .getInstance(SIGN_ALGORITHMS);
  119. signature.initVerify(pubKey);
  120. signature.update( content.getBytes() );
  121. // 验证方法 返回true则为比对成功
  122. boolean bverify = signature.verify( Base64.decode(sign) );
  123. return bverify;
  124. }
  125. catch (Exception e)
  126. {
  127. e.printStackTrace();
  128. }
  129. return false;
  130. }
  131. /**
  132. * 对象转HashMap
  133. * @param obj
  134. * @return
  135. */
  136. public static Map<String, Object> objectToMap(Object obj) {
  137. if (obj == null) {
  138. return null;
  139. }
  140. Map<String, Object> map = new HashMap<String, Object>();
  141. try {
  142. Field[] declaredFields = obj.getClass().getDeclaredFields();
  143. for (Field field : declaredFields) {
  144. field.setAccessible(true);
  145. map.put(field.getName(), field.get(obj));
  146. }
  147. } catch (Exception e) {
  148. }
  149. return map;
  150. }
  151. /**
  152. * @Description: 将签名的参数内容按参数名的字典顺序进行排序,并拼接为字符串
  153. */
  154. public static String getContent(Map<String,Object> map){
  155. //得到第三方签名 第三方会把sign也放在json里,故转map的时候需要把sign删除
  156. map.remove("shoppingAddrsInfo");
  157. map.entrySet().removeIf(entry -> entry.getValue() == null);
  158. // 将签名的参数内容按参数名的字典顺序进行排序,并拼接为字符串
  159. StringBuilder sb = new StringBuilder();
  160. map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEach(entry ->
  161. sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&")
  162. );
  163. return sb.toString().substring(0, sb.length() - 1);
  164. }
  165. /**
  166. * 签名方法
  167. * 因为很多处都需要用,特地封装一下,方便调用
  168. * @param paramStr 按字典顺序拼接过的字符串
  169. * @param publicKey 从数据库查询出来的第三方公钥
  170. * @param sign 第三方签名
  171. * @return
  172. */
  173. public static boolean signVerify(String paramStr,String publicKey,String sign){
  174. try {
  175. // 使用公钥进行验签
  176. boolean result = RSASignature.doCheck(paramStr, sign, publicKey);
  177. if (result){
  178. return true;
  179. }
  180. } catch (Exception e) {
  181. e.printStackTrace();
  182. }
  183. return false;
  184. }
  185. }

Base64类源码:

  1. package com.pay.utils;
  2. public final class Base64
  3. {
  4. static private final int BASELENGTH = 128;
  5. static private final int LOOKUPLENGTH = 64;
  6. static private final int TWENTYFOURBITGROUP = 24;
  7. static private final int EIGHTBIT = 8;
  8. static private final int SIXTEENBIT = 16;
  9. static private final int FOURBYTE = 4;
  10. static private final int SIGN = -128;
  11. static private final char PAD = '=';
  12. static private final boolean fDebug = false;
  13. static final private byte[] base64Alphabet = new byte[BASELENGTH];
  14. static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
  15. static
  16. {
  17. for (int i = 0; i < BASELENGTH; ++i)
  18. {
  19. base64Alphabet[i] = -1;
  20. }
  21. for (int i = 'Z'; i >= 'A'; i--)
  22. {
  23. base64Alphabet[i] = (byte) (i - 'A');
  24. }
  25. for (int i = 'z'; i >= 'a'; i--)
  26. {
  27. base64Alphabet[i] = (byte) (i - 'a' + 26);
  28. }
  29. for (int i = '9'; i >= '0'; i--)
  30. {
  31. base64Alphabet[i] = (byte) (i - '0' + 52);
  32. }
  33. base64Alphabet['+'] = 62;
  34. base64Alphabet['/'] = 63;
  35. for (int i = 0; i <= 25; i++)
  36. {
  37. lookUpBase64Alphabet[i] = (char) ('A' + i);
  38. }
  39. for (int i = 26, j = 0; i <= 51; i++, j++)
  40. {
  41. lookUpBase64Alphabet[i] = (char) ('a' + j);
  42. }
  43. for (int i = 52, j = 0; i <= 61; i++, j++)
  44. {
  45. lookUpBase64Alphabet[i] = (char) ('0' + j);
  46. }
  47. lookUpBase64Alphabet[62] = (char) '+';
  48. lookUpBase64Alphabet[63] = (char) '/';
  49. }
  50. private static boolean isWhiteSpace(char octect)
  51. {
  52. return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
  53. }
  54. private static boolean isPad(char octect)
  55. {
  56. return (octect == PAD);
  57. }
  58. private static boolean isData(char octect)
  59. {
  60. return (octect < BASELENGTH && base64Alphabet[octect] != -1);
  61. }
  62. /**
  63. * Encodes hex octects into Base64
  64. *
  65. * @param binaryData
  66. * Array containing binaryData
  67. * @return Encoded Base64 array
  68. */
  69. public static String encode(byte[] binaryData)
  70. {
  71. if (binaryData == null)
  72. {
  73. return null;
  74. }
  75. int lengthDataBits = binaryData.length * EIGHTBIT;
  76. if (lengthDataBits == 0)
  77. {
  78. return "";
  79. }
  80. int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
  81. int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
  82. int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
  83. : numberTriplets;
  84. char encodedData[] = null;
  85. encodedData = new char[numberQuartet * 4];
  86. byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
  87. int encodedIndex = 0;
  88. int dataIndex = 0;
  89. if (fDebug)
  90. {
  91. System.out.println("number of triplets = " + numberTriplets);
  92. }
  93. for (int i = 0; i < numberTriplets; i++)
  94. {
  95. b1 = binaryData[dataIndex++];
  96. b2 = binaryData[dataIndex++];
  97. b3 = binaryData[dataIndex++];
  98. if (fDebug)
  99. {
  100. System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
  101. }
  102. l = (byte) (b2 & 0x0f);
  103. k = (byte) (b1 & 0x03);
  104. byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
  105. : (byte) ((b1) >> 2 ^ 0xc0);
  106. byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
  107. : (byte) ((b2) >> 4 ^ 0xf0);
  108. byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
  109. : (byte) ((b3) >> 6 ^ 0xfc);
  110. if (fDebug)
  111. {
  112. System.out.println("val2 = " + val2);
  113. System.out.println("k4 = " + (k << 4));
  114. System.out.println("vak = " + (val2 | (k << 4)));
  115. }
  116. encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  117. encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
  118. encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
  119. encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
  120. }
  121. // form integral number of 6-bit groups
  122. if (fewerThan24bits == EIGHTBIT)
  123. {
  124. b1 = binaryData[dataIndex];
  125. k = (byte) (b1 & 0x03);
  126. if (fDebug)
  127. {
  128. System.out.println("b1=" + b1);
  129. System.out.println("b1<<2 = " + (b1 >> 2));
  130. }
  131. byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
  132. : (byte) ((b1) >> 2 ^ 0xc0);
  133. encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  134. encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
  135. encodedData[encodedIndex++] = PAD;
  136. encodedData[encodedIndex++] = PAD;
  137. }
  138. else if (fewerThan24bits == SIXTEENBIT)
  139. {
  140. b1 = binaryData[dataIndex];
  141. b2 = binaryData[dataIndex + 1];
  142. l = (byte) (b2 & 0x0f);
  143. k = (byte) (b1 & 0x03);
  144. byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
  145. : (byte) ((b1) >> 2 ^ 0xc0);
  146. byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
  147. : (byte) ((b2) >> 4 ^ 0xf0);
  148. encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  149. encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
  150. encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
  151. encodedData[encodedIndex++] = PAD;
  152. }
  153. return new String(encodedData);
  154. }
  155. /**
  156. * Decodes Base64 data into octects
  157. *
  158. * @param encoded
  159. * string containing Base64 data
  160. * @return Array containind decoded data.
  161. */
  162. public static byte[] decode(String encoded)
  163. {
  164. if (encoded == null)
  165. {
  166. return null;
  167. }
  168. char[] base64Data = encoded.toCharArray();
  169. // remove white spaces
  170. int len = removeWhiteSpace(base64Data);
  171. if (len % FOURBYTE != 0)
  172. {
  173. return null;// should be divisible by four
  174. }
  175. int numberQuadruple = (len / FOURBYTE);
  176. if (numberQuadruple == 0)
  177. {
  178. return new byte[0];
  179. }
  180. byte decodedData[] = null;
  181. byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
  182. char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
  183. int i = 0;
  184. int encodedIndex = 0;
  185. int dataIndex = 0;
  186. decodedData = new byte[(numberQuadruple) * 3];
  187. for (; i < numberQuadruple - 1; i++)
  188. {
  189. if (!isData((d1 = base64Data[dataIndex++]))
  190. || !isData((d2 = base64Data[dataIndex++]))
  191. || !isData((d3 = base64Data[dataIndex++]))
  192. || !isData((d4 = base64Data[dataIndex++])))
  193. {
  194. return null;
  195. }// if found "no data" just return null
  196. b1 = base64Alphabet[d1];
  197. b2 = base64Alphabet[d2];
  198. b3 = base64Alphabet[d3];
  199. b4 = base64Alphabet[d4];
  200. decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  201. decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  202. decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
  203. }
  204. if (!isData((d1 = base64Data[dataIndex++]))
  205. || !isData((d2 = base64Data[dataIndex++])))
  206. {
  207. return null;// if found "no data" just return null
  208. }
  209. b1 = base64Alphabet[d1];
  210. b2 = base64Alphabet[d2];
  211. d3 = base64Data[dataIndex++];
  212. d4 = base64Data[dataIndex++];
  213. if (!isData((d3)) || !isData((d4)))
  214. {// Check if they are PAD characters
  215. if (isPad(d3) && isPad(d4))
  216. {
  217. if ((b2 & 0xf) != 0)// last 4 bits should be zero
  218. {
  219. return null;
  220. }
  221. byte[] tmp = new byte[i * 3 + 1];
  222. System.arraycopy(decodedData, 0, tmp, 0, i * 3);
  223. tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
  224. return tmp;
  225. }
  226. else if (!isPad(d3) && isPad(d4))
  227. {
  228. b3 = base64Alphabet[d3];
  229. if ((b3 & 0x3) != 0)// last 2 bits should be zero
  230. {
  231. return null;
  232. }
  233. byte[] tmp = new byte[i * 3 + 2];
  234. System.arraycopy(decodedData, 0, tmp, 0, i * 3);
  235. tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  236. tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  237. return tmp;
  238. }
  239. else
  240. {
  241. return null;
  242. }
  243. }
  244. else
  245. { // No PAD e.g 3cQl
  246. b3 = base64Alphabet[d3];
  247. b4 = base64Alphabet[d4];
  248. decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  249. decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  250. decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
  251. }
  252. return decodedData;
  253. }
  254. /**
  255. * remove WhiteSpace from MIME containing encoded Base64 data.
  256. *
  257. * @param data
  258. * the byte array of base64 data (with WS)
  259. * @return the new length
  260. */
  261. private static int removeWhiteSpace(char[] data)
  262. {
  263. if (data == null)
  264. {
  265. return 0;
  266. }
  267. // count characters that's not whitespace
  268. int newSize = 0;
  269. int len = data.length;
  270. for (int i = 0; i < len; i++)
  271. {
  272. if (!isWhiteSpace(data[i]))
  273. {
  274. data[newSize++] = data[i];
  275. }
  276. }
  277. return newSize;
  278. }
  279. }

JAVA调用示例:

  1. public class Test {
  2. static String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnPo+UWWzx0Ny83acrRJCZy8sE5sYkuwvNYMTMd9ZHZQb8QRdZq6Ib+04+FocSHPt6OoMD+QB6ekbPyKY9NUGdtDVJ6AySGYlYnMT963lthsJrcJIL+QFyAlN2+BSh40ReTPISc2RpC7ahScsRmoj+wQE+HUSXvt7rqAdQM/ijthudPOI+DfGCtZjX7oS5pN3U2Ih7Qsx/51NpGbYKxA7ve+KCYDfmGbWDtwAChAFQnVZDyNOuusjyXbmHu2q+ey5y7Ztn2MyIQ2d/Ki3wDqLvZORgPpm6xm73+qh1A/9sjbsSc0cxPju21wP2tSKzNdegj6soXYUsWkrUM7Bcoi91wIDAQAB";
  3. static String privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCQuWPZmqnRPKbxtLkowlF+foMHM0NPr5D2dqWLAwmarUgdUd1L10WLIaJOjL36S1VOF4woDc8sd26ntO2LfP+TpAAIXpmsWRq9C4fY7Z24mR2EAu6FlDlHXvteYKh6XUYw36xn9fg9yh7yKjC0M8F/LTsmY1fKc4k0w0ARrWdY3IqpbFv8E/7WkUp6oBaza5+GiQ614fvmxzIAJaXg6D6USvmbPLMgxYFePOXyxDnA3YmC4SC4Zru3V0QVHewmy+VOHc+L3MJcMPPzMifZ5R2tXUM0mQPb3k9GuDY2etCI00jwhaw1IGIdgGsv8yJcwX9IBZYTsPIX5FUh9eVWKE/LAgMBAAECggEAdwfjtf/dF/i4niez+nAIMu++uNdSz2Fo6y0ebr0q0wseOu8wAcamrg4VvmFHh2saWEZJwk/JS5tXaZwHnChM1JOYa0nTPstykHXBX4vfowpcGk2G/Fqy2Z6nRDJfn3TD3EK7PC4z5C4vUaGduTiwNvdupN4kQKDSApFsSp3CWHSY0rE+kgNXfBrY6u16xc0QNRzoj+8/R1mno8OZCUEnFocRV4975mtAVrt3xsA+ejQqjhJnxUAKXVDMmOaVTyHwQyRrRDk7UzCpYax5YgVUbquRweOJl/HK9+zZzNcAy1cQUMjrAr9gUwCXZaKkdL0fujXXxPmfDLZF+QzoZrKVQQKBgQDqbps2vX/EGii8HjOFf4uvhMbSct37kWOiJMGqLIinxvrlxeWWShXhNp5eUPHg9i0bEZYSTLxRd2qM3xFsE6Wy/Zt/1x+9M7EDYafvJsSVsvmcJFBlfG2/VBT56iT4xDgHJOoDa8OeYQMbkJIEE+Xl+dXmfcfnijZkL66/JSebewKBgQCeCfb5D1ehRvvRw9gh0vXI18J0lc6wUEFS6A5UV7P27jmh80HgRnYlLzWryIAXcqvGACir9V6ZHCWfdzuhxxFqjSBqZPTMfKFHCxOk2YvHcGRQwsSZMGBfRKjyETFGRkPBphnq0sE3zKIKafB7Z0swBlcKB0yneIAilwUAsT2D8QKBgBPJ2lg4jrxi6OVYN0khhwz9zDqfb5V4pExfhelzcOWYqj0TA1o4Trh//8Y+VuyCWzRZu603xP2rctcJTVMuJWKCfcnAwvEZl+uNJrvNLfLk9KT1e8PVSP5JfqvJ0+0bww73UrmPMyf/UF/XSDwH4fQTrraSD3m/9O9oBvwjisBZAoGAQ5GXGl1I5hdnSwQkwDFmDHzTEu2J9TAa/cthdQYaV5T65xcOL0lw8e0BUXTj7yKD9p/Sw9Kgo225WDiuMjjeZWP5XAPV9ifC/JDr0SuB679N5ImhbK2WRqUgZn6bRqR8C6tsoU2Cdszy6ujofJppNxs+03bTeza18hQHe4hL+MECgYB9fEHhluk+fuKDfxVNTd98PBjatv4ZhMD3j1d+u0PWGZ2ajOBZ7m0ewso2n5otaTP2pxclmOq1/NX2KXUS2XVgX/bVZy1iUOmT8lUX3CHLUugQqdcv2oBL9n8n3rFhebps98MmUtVhx7qORrNU0aG6RlvFn3QBmF6mHXOuZ1nq6w==";
  4. public static void main(String[] args) throws Exception {
  5. Map<String,Object> params = new HashMap<>();
  6. params.put("merchantNo", merchantNo); // 商户号
  7. params.put("merchantOrderNo", merchantOrderNo); // 商户订单号
  8. params.put("currency", "CNY"); // 币种
  9. params.put("amount", "0.15");// 交易金额(单位:元)
  10. //签名数据按ASCII字码从小到大排序,所有键值对以“&”字符连接起来
  11. String data =
  12. RSASignature.getContent(JSON.parseObject(JSON.toJSONString(params)));
  13. System.out.println(data);
  14. // RSA签名
  15. String sign = RSASignature.sign(data, privateKey, "UTF-8");
  16. System.out.println(sign);
  17. String encryptData = RSAEncrypt.encryptForPrivateKey(str, privateKey);
  18. System.out.println("加密后内容:" + encryptData);
  19. //公钥解密
  20. //RSA解密
  21. String decryptData = RSAEncrypt.decryptForPublicKey(encryptData, publicKey);
  22. System.out.println("解密后内容:" + decryptData);
  23. }
  24. }

PHP加解密工具类源码:

  1. class RSA
  2. {
  3. public $privateKey = './rsa_private_key.pem'; //私钥地址
  4. public $publicKey = './rsa_public_key.pem'; //公钥地址
  5. public $pri_key = '';
  6. public $pub_key = '';
  7. /**
  8. * RSA constructor.
  9. * @param null $publicKeyPath
  10. * @param null $privateKeyPath
  11. * @param null $publicKey
  12. * @param null $privateKey
  13. * @throws FileNotFoundException
  14. */
  15. public function __construct($publicKeyPath=null, $privateKeyPath=null, $publicKey=null, $privateKey=null) {
  16. if ($this->checkKeyFile($publicKeyPath)) {
  17. $this->pub_key = openssl_pkey_get_public(file_get_contents($publicKeyPath));
  18. }
  19. if ($this->checkKeyFile($privateKeyPath)) {
  20. $this->pri_key = openssl_pkey_get_private(file_get_contents($privateKeyPath));
  21. }
  22. if (!is_null($publicKey)) {
  23. $this->pub_key = openssl_pkey_get_public($this->formatterPublicKey($publicKey));
  24. }
  25. if (!is_null($privateKey)) {
  26. $this->pri_key = openssl_pkey_get_private($this->formatterPrivateKey($privateKey));
  27. }
  28. }
  29. /**
  30. * 校验文件是否存在
  31. * @param $keyPath string 文件路径
  32. * @return bool
  33. * @throws FileNotFoundException
  34. */
  35. public function checkKeyFile($keyPath)
  36. {
  37. if (!is_null($keyPath)) {
  38. if(!file_exists($keyPath)) {
  39. throw new FileNotFoundException($keyPath);
  40. }
  41. return true;
  42. }
  43. return false;
  44. }
  45. /**
  46. * 格式化公钥
  47. * @param $publicKey string 公钥
  48. * @return string
  49. */
  50. public function formatterPublicKey($publicKey)
  51. {
  52. if (str_contains('-----BEGIN PUBLIC KEY-----', $publicKey)) return $publicKey;
  53. $str = chunk_split($publicKey, 64, PHP_EOL);//在每一个64字符后加一个\n
  54. $publicKey = "-----BEGIN PUBLIC KEY-----".PHP_EOL.$str."-----END PUBLIC KEY-----";
  55. return $publicKey;
  56. }
  57. /**
  58. * 格式化私钥
  59. * @param $privateKey string 公钥
  60. * @return string
  61. */
  62. public function formatterPrivateKey($privateKey)
  63. {
  64. if (str_contains('-----BEGIN RSA PRIVATE KEY-----', $privateKey)) return $privateKey;
  65. $str = chunk_split($privateKey, 64, PHP_EOL);//在每一个64字符后加一个\n
  66. $privateKey = "-----BEGIN RSA PRIVATE KEY-----".PHP_EOL.$str."-----END RSA PRIVATE KEY-----";
  67. return $privateKey;
  68. }
  69. /**
  70. * 私钥加密(分段加密)
  71. * emptyStr 需要加密字符串
  72. */
  73. public function encrypt($str) {
  74. $crypted = array();
  75. // $data = json_encode($str);
  76. $data = $str;
  77. $dataArray = str_split($data, 117);
  78. foreach($dataArray as $subData){
  79. $subCrypted = null;
  80. openssl_private_encrypt($subData, $subCrypted, $this->pri_key);
  81. $crypted[] = $subCrypted;
  82. }
  83. $crypted = implode('',$crypted);
  84. return base64_encode($crypted);
  85. }
  86. /**
  87. * 公钥解密(分段解密)
  88. * @encrypstr 加密字符串
  89. */
  90. public function decrypt($encryptstr) {
  91. // echo $encryptstr;exit;
  92. $encryptstr = base64_decode($encryptstr);
  93. $decrypted = array();
  94. $dataArray = str_split($encryptstr, 128);
  95. foreach($dataArray as $subData){
  96. $subDecrypted = null;
  97. openssl_public_decrypt($subData, $subDecrypted, $this->pub_key);
  98. $decrypted[] = $subDecrypted;
  99. }
  100. $decrypted = implode('',$decrypted);
  101. // openssl_public_decrypt(base64_decode($encryptstr),$decryptstr,$this->pub_key);
  102. return $decrypted;
  103. }
  104. }

PHP RSA签名验签:

  1. /**
  2. * 生成签名
  3. * @param string $signString 待签名字符串
  4. * @param [type] $priKey 私钥
  5. * @return string base64结果值
  6. */
  7. function getSign($signString,$priKey){
  8. $privKeyId = openssl_pkey_get_private($priKey);
  9. $signature = '';
  10. openssl_sign($signString, $signature, $privKeyId);
  11. openssl_free_key($privKeyId);
  12. return base64_encode($signature);
  13. }
  14. /**
  15. * 校验签名
  16. * @param string $pubKey 公钥
  17. * @param string $sign 签名
  18. * @param string $toSign 待签名字符串
  19. * @param string $signature_alg 签名方式 比如 sha1WithRSAEncryption 或者sha512
  20. * @return bool
  21. */
  22. function checkSign($pubKey,$sign,$toSign,$signature_alg=OPENSSL_ALGO_SHA1){
  23. $publicKeyId = openssl_pkey_get_public($pubKey);
  24. $result = openssl_verify($toSign, base64_decode($sign), $publicKeyId,$signature_alg);
  25. openssl_free_key($publicKeyId);
  26. return $result === 1 ? true : false;
  27. }

 PHP调用示例:

  1. $privateKey = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANSwa2pVnn4QbVxaNJg/1sudmGZL3eFOEOMk/ILagTnXNNtdV6pOslBOp5RBd93TdMZg/4KaAiluyOfg+WbExS7hg/cPXEiVfhF+4O+39uGmoYjlxAAs0dr+ZMAYjiZ+XKh8fuctD7mRYEkr7pBvqQbcRIDyJZpKIbyotcFudXVfAgMBAAECgYAJwJEcThK3Ww94pZY1yO+TZIWBY0coNoklsSN26If2W/zLdis33uXkMscSUDIr1K9NDVOJ7H/e4HqLz1AAO1ODLmFxflnyeEIKan6M/4NA8/7IF+Wu0FDQjNm2iKW68axKiW01j6yqq2JagG9kff5xbkzxriuWpmiDF0TWxzm6aQJBAPB2asI5dVr7bBC+sK7FjPQGNIu6X2NHeacHzUswSo7b4NgTucAkubjLTgpd3s8/FQoVBm4Ay7Juzc0DBjVUv2UCQQDibpd6lzY0E9cNGol83HDKJGUTmnpduE9PKYua019vx/tgoMOK4squqnV74IY7NkhP5V0djO0XYxD0EaFnmV9zAkAkp4hijuuqsMSqUMcR/R8dW4zK99/ufEi5A2Fx4qya1j2R8n/QIEkHOEZvIhwCr3T/knDmd8yVKHrKk3lwy7hZAkEAlB7SGpCGFaUQ3XKJk9NEOQd700oPV/V0dA1yVHKHEMFaMIiZweW/vmild8aVKHDG9vTMZ8NDaTQV6AMMeY+7/wJBANeLmqSHflwpMA9BdyTxmuRv8W2lLKsjGDBDnVaKf4hBltMll/e3/OPkg/BPew3lxrHkp3E1I6RyMTzmQxwXd78=';
  2. $rsa = new RSA(null, null, null, $privateKey);
  3. // 读取pem文件
  4. // $rsa = new RSA(null, public_path('rsa_private_key.pem'));
  5. $string = '{"phone":"15256232333","name":"张三","inAcctNo":"8239472342342342","idNo":"342422165897654326","inAcctBankName":"平安银行"}';
  6. $encryptstr = $rsa->encrypt($string);
  7. echo $encryptstr;
  8. //获取签名
  9. $sign = getSign($signString,$priKey);
  10. //验证签名
  11. $res = checkSign($pubKey,$sign,$signString);
  12. var_dump($res);//结果为 true

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/308270
推荐阅读
相关标签
  

闽ICP备14008679号