当前位置:   article > 正文

通过http协议调用api接口进行加密与解密操作_调用api接口 国密加密

调用api接口 国密加密

需求:通过对方提供的接口,对其接口进行解析它的api的json数据,并进行判断是否是同一数据,代码直接实现。

1、pom文件的引入

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>org.example</groupId>
  7. <artifactId>desd</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <dependencies>
  10. <!-- lombok依赖 -->
  11. <dependency>
  12. <groupId>org.projectlombok</groupId>
  13. <artifactId>lombok</artifactId>
  14. <optional>true</optional>
  15. </dependency>
  16. <!-- alibaba的fastjson -->
  17. <dependency>
  18. <groupId>com.alibaba</groupId>
  19. <artifactId>fastjson</artifactId>
  20. <version>1.2.60</version>
  21. </dependency>
  22. <!-- 工具包 -->
  23. <dependency>
  24. <groupId>org.apache.commons</groupId>
  25. <artifactId>commons-lang3</artifactId>
  26. <version>3.8.1</version>
  27. </dependency>
  28. <!-- rsa加密工具-->
  29. <dependency>
  30. <groupId>org.bouncycastle</groupId>
  31. <artifactId>bcprov-jdk15on</artifactId>
  32. <version>1.55</version>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.projectlombok</groupId>
  36. <artifactId>lombok</artifactId>
  37. <version>RELEASE</version>
  38. <scope>compile</scope>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.apache.directory.studio</groupId>
  42. <artifactId>org.apache.commons.codec</artifactId>
  43. <version>1.8</version>
  44. </dependency>
  45. <dependency>
  46. <groupId>org.springframework</groupId>
  47. <artifactId>spring-web</artifactId>
  48. <version>5.3.19</version>
  49. </dependency>
  50. <dependency>
  51. <groupId>org.testng</groupId>
  52. <artifactId>testng</artifactId>
  53. <version>RELEASE</version>
  54. <scope>compile</scope>
  55. </dependency>
  56. <!--HttpClient-->
  57. <dependency>
  58. <groupId>commons-httpclient</groupId>
  59. <artifactId>commons-httpclient</artifactId>
  60. <version>3.1</version>
  61. </dependency>
  62. <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
  63. <dependency>
  64. <groupId>org.apache.httpcomponents</groupId>
  65. <artifactId>httpclient</artifactId>
  66. <version>4.5.10</version>
  67. </dependency>
  68. <!--fastjson-->
  69. <dependency>
  70. <groupId>com.alibaba</groupId>
  71. <artifactId>fastjson</artifactId>
  72. <version>1.2.32</version>
  73. </dependency>
  74. <dependency>
  75. <groupId>org.testng</groupId>
  76. <artifactId>testng</artifactId>
  77. <version>RELEASE</version>
  78. <scope>compile</scope>
  79. </dependency>
  80. <dependency>
  81. <groupId>org.testng</groupId>
  82. <artifactId>testng</artifactId>
  83. <version>RELEASE</version>
  84. <scope>compile</scope>
  85. </dependency>
  86. <dependency>
  87. <groupId>org.apache.commons</groupId>
  88. <artifactId>commons-lang3</artifactId>
  89. <version>3.9</version>
  90. </dependency>
  91. </dependencies>
  92. </project>

(2)加密算法工具类

  1. package com.gblfy.util;
  2. import java.security.Key;
  3. import java.security.NoSuchAlgorithmException;
  4. import java.security.NoSuchProviderException;
  5. import java.security.SecureRandom;
  6. import java.security.Security;
  7. import java.util.Arrays;
  8. import javax.crypto.Cipher;
  9. import javax.crypto.KeyGenerator;
  10. import javax.crypto.spec.SecretKeySpec;
  11. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  12. import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
  13. /**
  14. * sm4加密算法工具类
  15. * @explain sm4加密、解密与加密结果验证 可逆算法
  16. */
  17. public class Sm4Util {
  18. static {
  19. Security.addProvider(new BouncyCastleProvider());
  20. }
  21. private static final String ENCODING = "UTF-8";
  22. public static final String ALGORITHM_NAME = "SM4";
  23. // 加密算法/分组加密模式/分组填充方式
  24. // PKCS5Padding-以8个字节为一组进行分组加密
  25. // 定义分组加密模式使用:PKCS5Padding
  26. public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
  27. // 128-32位16进制;256-64位16进制
  28. public static final int DEFAULT_KEY_SIZE = 128;
  29. /**
  30. * 生成ECB暗号
  31. * @explain ECB模式(电子密码本模式:Electronic codebook)
  32. * @param algorithmName 算法名称
  33. * @param mode 模式
  34. * @param key
  35. * @return
  36. * @throws Exception
  37. */
  38. private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {
  39. Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
  40. Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
  41. cipher.init(mode, sm4Key);
  42. return cipher;
  43. }
  44. /**
  45. * 自动生成密钥
  46. * @explain
  47. * @return
  48. * @throws NoSuchAlgorithmException
  49. * @throws NoSuchProviderException
  50. */
  51. public static byte[] generateKey() throws Exception {
  52. return generateKey(DEFAULT_KEY_SIZE);
  53. }
  54. //加密******************************************
  55. /**
  56. * @explain 系统产生秘钥
  57. * @param keySize
  58. * @return
  59. * @throws Exception
  60. */
  61. public static byte[] generateKey(int keySize) throws Exception {
  62. KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
  63. kg.init(keySize, new SecureRandom());
  64. return kg.generateKey().getEncoded();
  65. }
  66. /**
  67. * sm4加密
  68. * @explain 加密模式:ECB 密文长度不固定,会随着被加密字符串长度的变化而变化
  69. * @param hexKey 16进制密钥(忽略大小写)
  70. * @param paramStr 待加密字符串
  71. * @return 返回16进制的加密字符串
  72. * @throws Exception
  73. */
  74. public static String encryptEcb(String hexKey, String paramStr) throws Exception {
  75. String cipherText = "";
  76. // 16进制字符串-->byte[]
  77. byte[] keyData = ByteUtils.fromHexString(hexKey);
  78. // String-->byte[]
  79. byte[] srcData = paramStr.getBytes(ENCODING);
  80. // 加密后的数组
  81. byte[] cipherArray = encrypt_Ecb_Padding(keyData, srcData);
  82. // byte[]-->hexString
  83. cipherText = ByteUtils.toHexString(cipherArray);
  84. return cipherText;
  85. }
  86. /**
  87. * 加密模式之Ecb
  88. * @param key
  89. * @param data
  90. * @return
  91. * @throws Exception
  92. */
  93. public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throws Exception {
  94. Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);//声称Ecb暗号,通过第二个参数判断加密还是解密
  95. return cipher.doFinal(data);
  96. }
  97. //解密****************************************
  98. /**
  99. * sm4解密
  100. * @explain 解密模式:采用ECB
  101. * @param hexKey 16进制密钥
  102. * @param cipherText 16进制的加密字符串(忽略大小写)
  103. * @return 解密后的字符串
  104. * @throws Exception
  105. */
  106. public static String decryptEcb(String hexKey, String cipherText) throws Exception {
  107. // 用于接收解密后的字符串
  108. String decryptStr = "";
  109. // hexString-->byte[]
  110. byte[] keyData = ByteUtils.fromHexString(hexKey);
  111. // hexString-->byte[]
  112. byte[] cipherData = ByteUtils.fromHexString(cipherText);
  113. // 解密
  114. byte[] srcData = decrypt_Ecb_Padding(keyData, cipherData);
  115. // byte[]-->String
  116. decryptStr = new String(srcData, ENCODING);
  117. return decryptStr;
  118. }
  119. /**
  120. * 解密
  121. * @explain
  122. * @param key
  123. * @param cipherText
  124. * @return
  125. * @throws Exception
  126. */
  127. public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throws Exception {
  128. Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);//生成Ecb暗号,通过第二个参数判断加密还是解密
  129. return cipher.doFinal(cipherText);
  130. }
  131. /**
  132. * 校验加密前后的字符串是否为同一数据
  133. * @explain
  134. * @param hexKey 16进制密钥(忽略大小写)
  135. * @param cipherText 16进制加密后的字符串
  136. * @param paramStr 加密前的字符串
  137. * @return 是否为同一数据
  138. * @throws Exception
  139. */
  140. public static boolean verifyEcb(String hexKey, String cipherText, String paramStr) throws Exception {
  141. // 用于接收校验结果
  142. boolean flag = false;
  143. // hexString-->byte[]
  144. byte[] keyData = ByteUtils.fromHexString(hexKey);
  145. // 将16进制字符串转换成数组
  146. byte[] cipherData = ByteUtils.fromHexString(cipherText);
  147. // 解密
  148. byte[] decryptData = decrypt_Ecb_Padding(keyData, cipherData);
  149. // 将原字符串转换成byte[]
  150. byte[] srcData = paramStr.getBytes(ENCODING);
  151. // 判断2个数组是否一致
  152. flag = Arrays.equals(decryptData, srcData);
  153. return flag;
  154. }
  155. }

(3)httpApi工具类与测试

  1. package com.gblfy.util;
  2. import com.alibaba.fastjson.JSONObject;
  3. import lombok.val;
  4. import org.apache.commons.lang3.StringUtils;
  5. import org.apache.commons.lang3.exception.ExceptionUtils;
  6. import org.apache.http.HttpResponse;
  7. import org.apache.http.HttpStatus;
  8. import org.apache.http.NameValuePair;
  9. import org.apache.http.client.HttpClient;
  10. import org.apache.http.client.entity.UrlEncodedFormEntity;
  11. import org.apache.http.client.methods.HttpGet;
  12. import org.apache.http.client.methods.HttpPost;
  13. import org.apache.http.client.utils.URIBuilder;
  14. import org.apache.http.entity.StringEntity;
  15. import org.apache.http.impl.client.HttpClientBuilder;
  16. import org.apache.http.message.BasicNameValuePair;
  17. import org.apache.http.util.EntityUtils;
  18. import org.slf4j.Logger;
  19. import org.slf4j.LoggerFactory;
  20. import java.io.*;
  21. import java.net.HttpURLConnection;
  22. import java.net.URI;
  23. import java.net.URL;
  24. import java.nio.charset.Charset;
  25. import java.util.*;
  26. /**
  27. * @author Mundo
  28. * @ClassName: HttpClientUtil
  29. * @Description: TODO
  30. */
  31. public class HttpApiUtil {
  32. private static final Logger logger = LoggerFactory.getLogger(HttpApiUtil.class);
  33. /**
  34. *
  35. * @param url 请求路径
  36. * @param params 参数
  37. * @return
  38. */
  39. public static String doGet(String url, Map<String, String> params) {
  40. // 返回结果
  41. String result = "";
  42. // 创建HttpClient对象
  43. HttpClient httpClient = HttpClientBuilder.create().build();
  44. HttpGet httpGet = null;
  45. try {
  46. // 拼接参数,可以用URIBuilder,也可以直接拼接在?传值,拼在url后面,如下--httpGet = new
  47. // HttpGet(uri+"?id=123");
  48. URIBuilder uriBuilder = new URIBuilder(url);
  49. if (null != params && !params.isEmpty()) {
  50. for (Map.Entry<String, String> entry : params.entrySet()) {
  51. uriBuilder.addParameter(entry.getKey(), entry.getValue());
  52. // 或者用
  53. // 顺便说一下不同(setParameter会覆盖同名参数的值,addParameter则不会)
  54. // uriBuilder.setParameter(entry.getKey(), entry.getValue());
  55. }
  56. }
  57. URI uri = uriBuilder.build();
  58. // 创建get请求
  59. httpGet = new HttpGet(uri);
  60. logger.info("访问路径:" + uri);
  61. HttpResponse response = httpClient.execute(httpGet);
  62. if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {// 返回200,请求成功
  63. // 结果返回
  64. result = EntityUtils.toString(response.getEntity());
  65. logger.info("请求成功!,返回数据:" + result);
  66. } else {
  67. logger.info("请求失败!");
  68. }
  69. } catch (Exception e) {
  70. logger.info("请求失败!");
  71. logger.error(ExceptionUtils.getStackTrace(e));
  72. } finally {
  73. // 释放连接
  74. if (null != httpGet) {
  75. httpGet.releaseConnection();
  76. }
  77. }
  78. return result;
  79. }
  80. /**
  81. * @param url
  82. * @param params
  83. * @return
  84. * @Title: doPost
  85. * @Description: post请求
  86. * @author Mundo
  87. */
  88. public static String doPost(String url, Map<String, String> params) {
  89. String result = "";
  90. // 创建httpclient对象
  91. HttpClient httpClient = HttpClientBuilder.create().build();
  92. HttpPost httpPost = new HttpPost(url);
  93. try { // 参数键值对
  94. if (null != params && !params.isEmpty()) {
  95. List<NameValuePair> pairs = new ArrayList<NameValuePair>();
  96. NameValuePair pair = null;
  97. for (String key : params.keySet()) {
  98. pair = new BasicNameValuePair(key, params.get(key));
  99. pairs.add(pair);
  100. }
  101. // 模拟表单
  102. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(pairs);
  103. httpPost.setEntity(entity);
  104. }
  105. HttpResponse response = httpClient.execute(httpPost);
  106. if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
  107. result = EntityUtils.toString(response.getEntity(), "utf-8");
  108. logger.info("返回数据:>>>" + result);
  109. } else {
  110. logger.info("请求失败!,url:" + url);
  111. }
  112. } catch (Exception e) {
  113. logger.error("请求失败");
  114. logger.error(ExceptionUtils.getStackTrace(e));
  115. e.printStackTrace();
  116. } finally {
  117. if (null != httpPost) {
  118. // 释放连接
  119. httpPost.releaseConnection();
  120. }
  121. }
  122. return result;
  123. }
  124. /**
  125. * post发送json字符串
  126. * @param url
  127. * @param params
  128. * @return 返回数据
  129. * @Title: sendJsonStr
  130. */
  131. public static String sendJsonStr(String url, String params) {
  132. String result = "";
  133. HttpClient httpClient = HttpClientBuilder.create().build();
  134. HttpPost httpPost = new HttpPost(url);
  135. try {
  136. httpPost.addHeader("Content-type", "application/json; charset=utf-8");
  137. httpPost.setHeader("Accept", "application/json");
  138. if (StringUtils.isNotBlank(params)) {
  139. httpPost.setEntity(new StringEntity(params, Charset.forName("UTF-8")));
  140. }
  141. HttpResponse response = httpClient.execute(httpPost);
  142. if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
  143. result = EntityUtils.toString(response.getEntity());
  144. logger.info("返回数据:" + result);
  145. } else {
  146. logger.info("请求失败");
  147. }
  148. } catch (IOException e) {
  149. logger.error("请求异常");
  150. logger.error(ExceptionUtils.getStackTrace(e));
  151. }
  152. return result;
  153. }
  154. /**
  155. * 发送http请求的obj报文(内置转json)
  156. *
  157. * @param url
  158. * @param obj
  159. * @return
  160. */
  161. public static String postJson(String url, Object obj) {
  162. HttpURLConnection conn = null;
  163. try {
  164. // 创建一个URL对象
  165. URL mURL = new URL(url);
  166. // 调用URL的openConnection()方法,获取HttpURLConnection对象
  167. conn = (HttpURLConnection) mURL.openConnection();
  168. conn.setRequestMethod("POST");// 设置请求方法为post
  169. /* conn.setReadTimeout(5000);// 设置读取超时为5秒
  170. conn.setConnectTimeout(10000);// 设置连接网络超时为10秒*/
  171. conn.setDoOutput(true);// 设置此方法,允许向服务器输出内容
  172. // 设置文件类型:
  173. conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
  174. // 设置接收类型否则返回415错误
  175. conn.setRequestProperty("accept", "application/json");
  176. int len = 0;
  177. // post请求的参数
  178. byte[] buf = new byte[10240];
  179. //
  180. String data = JSONObject.toJSONString(obj);
  181. // 获得一个输出流,向服务器写数据,默认情况下,系统不允许向服务器输出内容
  182. OutputStream out = conn.getOutputStream();// 获得一个输出流,向服务器写数据
  183. out.write(data.getBytes());
  184. out.flush();
  185. out.close();
  186. int responseCode = conn.getResponseCode();// 调用此方法就不必再使用conn.connect()方法
  187. if (responseCode == 200) {
  188. InputStream is = conn.getInputStream();
  189. String state = getStringFromInputStream(is);
  190. return state;
  191. } else {
  192. System.out.print("访问失败" + responseCode);
  193. }
  194. } catch (Exception e) {
  195. e.printStackTrace();
  196. } finally {
  197. if (conn != null) {
  198. conn.disconnect();// 关闭连接
  199. }
  200. }
  201. return null;
  202. }
  203. public static String getStringFromInputStream(InputStream is) throws IOException {
  204. ByteArrayOutputStream os = new ByteArrayOutputStream();
  205. // 模板代码 必须熟练
  206. byte[] buffer = new byte[1024];
  207. int len = -1;
  208. // 一定要写len=is.read(buffer)
  209. // 如果while((is.read(buffer))!=-1)则无法将数据写入buffer中
  210. while ((len = is.read(buffer)) != -1) {
  211. os.write(buffer, 0, len);
  212. }
  213. is.close();
  214. String state = os.toString();// 把流中的数据转换成字符串,采用的编码是utf-8(模拟器默认编码)
  215. os.close();
  216. return state;
  217. }
  218. /**
  219. * post方式请求服务器(http协议)
  220. *
  221. * @param url 请求地址
  222. * @param content 参数
  223. * @param charset 编码
  224. * @return
  225. * @throws
  226. * @throws
  227. * @throws IOException
  228. */
  229. public static byte[] post(String url, String content, String charset) throws IOException {
  230. URL console = new URL(url);
  231. HttpURLConnection conn = (HttpURLConnection) console.openConnection();
  232. conn.setDoOutput(true);
  233. // 设置请求头
  234. conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
  235. conn.connect();
  236. DataOutputStream out = new DataOutputStream(conn.getOutputStream());
  237. out.write(content.getBytes(charset));
  238. // 刷新、关闭
  239. out.flush();
  240. out.close();
  241. InputStream is = conn.getInputStream();
  242. if (is != null) {
  243. ByteArrayOutputStream outStream = new ByteArrayOutputStream();
  244. byte[] buffer = new byte[1024];
  245. int len = 0;
  246. while ((len = is.read(buffer)) != -1) {
  247. outStream.write(buffer, 0, len);
  248. }
  249. is.close();
  250. return outStream.toByteArray();
  251. }
  252. return null;
  253. }
  254. public static void main(String[] args) {
  255. Map<String, String> map = new HashMap<String, String>();
  256. map.put("id", UUID.randomUUID().toString());
  257. map.put("name", "gblfy");
  258. // String json = doGet("https://api.instagram.com/locations/search", map);
  259. String json = doPost("https://oapi.dingtalk.com/topapi/org/union/trunk/get", map);
  260. System.out.println("post请求调用成功,返回数据是:" + json);
  261. // System.out.println("get请求调用成功,返回数据是:" + json);
  262. try {
  263. System.out.println("开始测试SM4加密解密====================");
  264. // String json ="https://api.instagram.com/locations/search";
  265. System.out.println("加密前:"+json);
  266. //自定义的32位16进制秘钥
  267. String key = "86C63180C2806ED1F47B859DE501215B";
  268. String cipher = Sm4Util.encryptEcb(key,json);//sm4加密
  269. System.out.println("加密后:"+cipher);
  270. System.out.println("校验:"+Sm4Util.verifyEcb(key,cipher,json));//校验加密前后是否为同一数据
  271. json = Sm4Util.decryptEcb(key,cipher);//解密
  272. System.out.println("解密后:"+json);
  273. System.out.println("结束===================");
  274. } catch (Exception e) {
  275. e.printStackTrace();
  276. }
  277. }
  278. }

(4)运行输出,如图所示:

即输出数据:

  1. post请求调用成功,返回数据是:{"errcode":88,"sub_code":"40000","sub_msg":"access_token is blank","errmsg":"ding talk error[subcode=40000,submsg=access_token is blank]","request_id":"15rrg0f4hakki"}
  2. 开始测试SM4加密解密====================
  3. 加密前:{"errcode":88,"sub_code":"40000","sub_msg":"access_token is blank","errmsg":"ding talk error[subcode=40000,submsg=access_token is blank]","request_id":"15rrg0f4hakki"}
  4. 加密后:1fc77cf74a5af18d46e8b5da00cf31683c2cd2ef6d2f0b0bcb99ee5a62e916b39a4674ae91abaaea095555a644059c4945c4264b0c751296842c24fc1913fe7a60a670c4933ff70c2fcbb720e69ccea9c893b7fb3d2733f880fbc67c414432ff342e23ba974e2a22667b2073511f91fe93068a1d5d0c07db710276d3923ca05459dcff8e81b2d9a71ec0d69052f66cfda37d354d9d850d8884ee4cd4c9d1cf20afc7c0060921ff02dbad5da0ecbbeee5
  5. 校验:true
  6. 解密后:{"errcode":88,"sub_code":"40000","sub_msg":"access_token is blank","errmsg":"ding talk error[subcode=40000,submsg=access_token is blank]","request_id":"15rrg0f4hakki"}
  7. 结束===================
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/616289
推荐阅读
相关标签