SOP页面跳转设计 RAS AES加密算法应用跨服务免登陆接口设计
SOP页面跳转设计 RAS AES加密算法应用跨服务免登陆接口设计
SOP,是 Standard Operating Procedure三个单词中首字母的大写 ,即标准作业程序,指将某一事件的标准操作步骤和要求以统一的格式描述出来,用于指导和规范日常的工作。
加密/加签过程:
1.动态随机生成AES密钥aesKey,而不是静态的AES密钥。提高安全性。
2.使用该AES对传输的接口数据data加密。 比如:username=AES(username原文,aesKey)&age=AES(age原文,aesKey)
3.使用RSA公钥对aesKey加密,作为参数传递 prikey=RSA(aeskey,公钥)
以上完整的路径:http://IP地址+端口/path?username=AES(username,aesKey)&age=AES(age,aesKey)&prikey=RSA(aeskey,公钥)
解密/解签过程:
1.先用私钥从prikey解密获取aesKey
2.用aesKey解密username,age获得username原文,age原文
* Invalid AES key length: 33 bytes
*
* 如果未指定init LEN,则根据参数的key自适应。AES KEY长度为 16位,24位,32位。
* 否则可以指定AES KEY长度
* // KeyGenerator kgen = KeyGenerator.getInstance(TYPE);
* // //Wrong keysize: must be equal to 128, 192 or 256
* // kgen.init(LEN); //128 / 8 = 16
*
* 经过测试发现:
* keysize: must be equal to 128, 192 or 256
* aes key长度 16,24,32
* 以上的两个条件相互都成立,而不是如下的第一组,第二组,第三组的强制配对。
DEMO代码示例:
package com.example.core.mydemo.spi; import com.alibaba.fastjson.JSONObject; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date; /**
* Invalid AES key length: 33 bytes
*
* 如果未指定init LEN,则根据参数的key自适应。AES KEY长度为 16位,24位,32位。
* 否则可以指定AES KEY长度
* // KeyGenerator kgen = KeyGenerator.getInstance(TYPE);
* // //Wrong keysize: must be equal to 128, 192 or 256
* // kgen.init(LEN); //128 / 8 = 16
*
* 经过测试发现:
* keysize: must be equal to 128, 192 or 256
* aes key长度 16,24,32
* 以上的两个条件相互都成立,而不是如下的第一组,第二组,第三组的强制配对。
*/
public class AesUtil { //算法
private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
//密钥 (静态aesKey)
//第一组
public static final String KEY = "9862ecf540c64534";
// public static final String KEY = "yyyyyyyyyyyyyyyy"; //16位
//
private static final Integer LEN = 128; //第二组
// public static final String KEY = "yyyyyyyyyyyyyyyy91a1e003c11b414e"; //32位
// private static final Integer LEN = 256; //第三组
// public static final String KEY = "yyyyyyyyyyyyyyyy91a1e003"; //24位
// private static final Integer LEN = 192; // 加密类型
private static final String TYPE = "AES"; /**
* aes加密 - 静态aesKey
*
* @param content
* @return
* @throws Exception
*/
public static String aesEncrypt(String content) {
try {
return aesEncrypt(content, KEY);
} catch (Exception e) {
e.printStackTrace();
return "";
}
} /**
* aes解密 - 静态aesKey
*
* @param encrypt 内容
* @return
* @throws Exception
*/
public static String aesDecrypt(String encrypt) {
try {
return aesDecrypt(encrypt, KEY);
} catch (Exception e) {
e.printStackTrace();
return "";
}
} /**
* 将base 64 code AES解密
*
* @param encryptStr 待解密的base 64 code
* @param decryptKey 解密密钥
* @return 解密后的string
* @throws Exception
*/
public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
return isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
} /**
* AES解密
*
* @param encryptBytes 待解密的byte[]
* @param decryptKey 解密密钥
* @return 解密后的String
* @throws Exception
*/
public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance(TYPE);
//Wrong keysize: must be equal to 128, 192 or 256
kgen.init(LEN); Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), TYPE));
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes);
} /**
* base 64 decode
*
* @param base64Code 待解码的base 64 code
* @return 解码后的byte[]
* @throws Exception
*/
public static byte[] base64Decode(String base64Code) throws Exception {
return isEmpty(base64Code) ? null : Base64.getDecoder().decode(base64Code);
} /**
* AES加密为base 64 code
*
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的base 64 code
* @throws Exception
*/
public static String aesEncrypt(String content, String encryptKey) throws Exception {
return base64Encode(aesEncryptToBytes(content, encryptKey));
} /**
* base 64 encode
*
* @param bytes 待编码的byte[]
* @return 编码后的base 64 code
*/
public static String base64Encode(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
} /**
* AES加密
*
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的byte[]
* @throws Exception
*/
public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance(TYPE);
//Wrong keysize: must be equal to 128, 192 or 256
kgen.init(LEN); //128 / 8 = 16 Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), TYPE));
return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
} /**
* 将byte[]转为各种进制的字符串
*
* @param bytes byte[]
* @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
* @return 转换后的字符串
*/
public static String binary(byte[] bytes, int radix) {
return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
} public static boolean isEmpty(CharSequence cs) {
return cs == null || cs.length() == 0;
} /**
* 测试
* output:
* 对比:RASPublicAuthUtil.java输出结果 对比一致
* username AES加密后的数据:wG2GS4DxYko57DoL0kAAWA%3D%3D
* username解码:wG2GS4DxYko57DoL0kAAWA==
*
*encrypt=wG2GS4DxYko57DoL0kAAWA==
* encodeEncrypt=wG2GS4DxYko57DoL0kAAWA%3D%3D
* decrypt=admin
*
*/
public static void main(String[] args) throws Exception {
// JSONObject jsonObject = new JSONObject();
// jsonObject.put("ticketId", "8310000002021051115277C");
// jsonObject.put("serviceItemId", "100000000708");
// jsonObject.put("timestamp", new Date());
// System.out.println("json data=" + jsonObject.toJSONString());
// String encrypt = aesEncrypt(jsonObject.toJSONString());
//aes加密
String encrypt = aesEncrypt("admin");
System.out.println("encrypt=" + encrypt);
//aes编码
String encodeEncrypt = URLEncoder.encode(encrypt, "UTF-8");
System.out.println("encodeEncrypt=" + encodeEncrypt); //aes解密
String decodeEncrypt = URLDecoder.decode(encodeEncrypt,"UTF-8");
String decrypt = aesDecrypt(decodeEncrypt);
System.out.println("decrypt=" + decrypt);
}
} package com.example.core.mydemo.spi; import com.alibaba.fastjson.JSONObject; import javax.crypto.Cipher;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.UUID; /**
**/
public class RSAPublicAuthUtil { // Base64解密
private static final Base64.Decoder decoder = Base64.getDecoder();
// Base64加密
private static final Base64.Encoder encoder = Base64.getEncoder(); /**
* 非对称密钥算法
*/
public static final String KEY_ALGORITHM = "RSA"; /**
* 公钥
*/
private static final String PUBLIC_KEY = "可以使用支付宝开放平台开发助手.exe工具生成";
/**
* 私钥
*/
private static final String PRIVATE_KEY = "可以使用支付宝开放平台开发助手.exe工具生成"; /**
* @param data
* @throws
* @Description:
* @return: java.lang.String
* @Author: MeiQi
* @Date: 2021/7/12 20:50
**/
public static String encryptByPublicKey(String data)throws Exception {
byte[] key_byte = decoder.decode(PUBLIC_KEY);
byte[] encrypt_str = encryptByPublicKey(decoder.decode(data), key_byte);
return encoder.encodeToString(encrypt_str);
} /**
* @param data 待加密数据
* @param key 密钥
* @throws
* @Description: 公钥加密
* @return: byte[] 加密数据
* @Author: MeiQi
* @Date: 2021/7/12 20:51
**/
private static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
//实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//初始化公钥
//密钥材料转换
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
//产生公钥
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
//数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return cipher.doFinal(data);
} /**
* 私钥解密
* @param secretText 待解密的密文字符串
* @return 解密后的明文
*/
public static String decryptByPrivateKey(String secretText) {
try {
String privateKeyStr = PRIVATE_KEY;
String input_charset = "UTF-8";
// 生成私钥
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKeyStr));
// 密文解码
byte[] secretTextDecoded = decoder.decode(secretText);
byte[] tempBytes = cipher.doFinal(secretTextDecoded);
// return new String(tempBytes);
return encoder.encodeToString(tempBytes);
} catch (Exception e) {
throw new RuntimeException("解密字符串[" + secretText + "]时遇到异常", e);
}
} /**
* 得到私钥
* @param key 密钥字符串(经过base64编码)
* @throws Exception
*/
private static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = decoder.decode(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
} /**
* output:
* 公钥:~~
* 原文:admin
* 原文:25
* aesKey:9862ecf540c64534
* username AES加密后的数据:wG2GS4DxYko57DoL0kAAWA%3D%3D
* age AES加密后的数据:NUjk8UtCDZq7U8HhRNixNQ%3D%3D
* 使用公钥加密prikey后的数据:NJ2dUzqqUwzcrYqV5GX0xKDo9eBuC1hjvTUAmtZmC9xoTX7nc0JhEErO2AZRyCS47Bc6CZi68MWSKsBt9bNxIfkY3ciGWOxSgHNhOVpWM8wEjWb6q%2BNcoLV9p7wapdur43v3jdcGFhzD0ugmDMiTPhCPfp0Dz3s9qTZD6rN1uc0%3D
* http://localhost:8010/#/index?&username=wG2GS4DxYko57DoL0kAAWA%3D%3D&age=NUjk8UtCDZq7U8HhRNixNQ%3D%3D&prikey=NJ2dUzqqUwzcrYqV5GX0xKDo9eBuC1hjvTUAmtZmC9xoTX7nc0JhEErO2AZRyCS47Bc6CZi68MWSKsBt9bNxIfkY3ciGWOxSgHNhOVpWM8wEjWb6q%2BNcoLV9p7wapdur43v3jdcGFhzD0ugmDMiTPhCPfp0Dz3s9qTZD6rN1uc0%3D
* prikey解码:NJ2dUzqqUwzcrYqV5GX0xKDo9eBuC1hjvTUAmtZmC9xoTX7nc0JhEErO2AZRyCS47Bc6CZi68MWSKsBt9bNxIfkY3ciGWOxSgHNhOVpWM8wEjWb6q+NcoLV9p7wapdur43v3jdcGFhzD0ugmDMiTPhCPfp0Dz3s9qTZD6rN1uc0=
* prikey解密:9862ecf540c64534
* username解码:wG2GS4DxYko57DoL0kAAWA==
* username解密:admin
* age解码:NUjk8UtCDZq7U8HhRNixNQ==
* age解密:25
*/ /**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//发送端
System.out.println("公钥:" + PUBLIC_KEY);
String username = "admin";
System.out.println("原文:" + username);
String age = "25";
System.out.println("原文:" + age); String nonceStr = UUID.randomUUID().toString().replace("-", "");
String aesKey = nonceStr.substring(0, 16);
System.out.println("aesKey:" + aesKey); username = AesUtil.aesEncrypt(username, aesKey);
username = URLEncoder.encode(username, "UTF-8");
System.out.println("username AES加密后的数据:" + username); age = AesUtil.aesEncrypt(age, aesKey);
age = URLEncoder.encode(age, "UTF-8");
System.out.println("age AES加密后的数据:" + age); //发送端进行数据的加密
String prikey = RSAPublicAuthUtil.encryptByPublicKey(aesKey);
prikey = URLEncoder.encode(prikey, "UTF-8");
System.out.println("使用公钥加密prikey后的数据:" + prikey); String base_url = "http://localhost:8010/#/index?";
System.out.println(base_url.concat("&username=").concat(username).concat("&age=").concat(age).concat("&prikey=").concat(prikey)); //接收端
prikey = URLDecoder.decode(prikey,"UTF-8");
System.out.println("prikey解码:" + prikey);
String decryAes = RSAPublicAuthUtil.decryptByPrivateKey(prikey);
System.out.println("prikey解密:" + decryAes); username = URLDecoder.decode(username,"UTF-8");
System.out.println("username解码:" + username);
String decryUsernameStr = AesUtil.aesDecrypt(username,decryAes);
System.out.println("username解密:" + decryUsernameStr); age = URLDecoder.decode(age,"UTF-8");
System.out.println("age解码:" + age);
String decryAgeStr = AesUtil.aesDecrypt(age,decryAes);
System.out.println("age解密:" + decryAgeStr); }
}
RSA公私钥生成可以使用支付宝开放平台开发助手.exe工具生成
SOP页面跳转设计 RAS AES加密算法应用跨服务免登陆接口设计的更多相关文章
- Python之登陆接口设计
刚刚开始学习Python,第一个编写的程序. import os user_file = open('use_file.txt', 'r') user_list = user_file.readlin ...
- python——登陆接口设计(循环方法)
近日重新整理了登陆接口设计程序,感觉以前的代码没有注释,让园子的其他童鞋读起来比较费劲.也没有流程图和程序运行说明. 1.流程图 2.user_file.txt&lock_file.txt文件 ...
- Web设计中打开新页面或页面跳转的方法 js跳转页面
Web设计中打开新页面或页面跳转的方法 一.asp.net c# 打开新页面或页面跳转 1. 最常用的页面跳转(原窗口被替代):Response.Redirect("newpage.aspx ...
- web设计页面跳转的方法
一.asp.net c# 打开新页面或页面跳转 1. 最常用的页面跳转(原窗口被替代):Response.Redirect("newpage.aspx"); 2. 利用url地址打 ...
- Web设计中打开新页面或页面跳转的方法
一.asp.net c# 打开新页面或页面跳转 1. 最常用的页面跳转(原窗口被替代):Response.Redirect("newpage.aspx"); 2. 利用url地址打 ...
- wex5 教程 之 图文讲解 登陆,注册,页面跳转
视频教程地址:http://v.youku.com/v_show/id_XMTc3OTE0Nzg0NA==.html 效果预览: 登陆页面 首页用windowContainer装载 注册页面 登陆 ...
- Android实现页面跳转、ListView及其事件
Android实现页面跳转.ListView及其事件 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 工程内容 进入主页面后,使用ListView实现特 ...
- ASP.NET页面跳转的三种方法比较
在ASP.NET下,经常需要在页面之间跳转,下面我们来分别介绍一下关于.NET中Response.Redirect(),Sever.Execute(),Server.Transfer() 三种页面跳转 ...
- Behavior的使用(一):页面跳转NavigateToPageAction
Behavior的使用,让UI设计师能够更加方便的进行UI设计,更高效地和开发进行合作.Behavior有三种触发方式:EventTriggerBehavior事件触发,DataTriggerBeha ...
- ASP.NET页面跳转的三大方法详解
ASP.NET页面跳转有什么方法呢?,现在给大家介绍三种方法,他们的区别是什么呢?让我们开始吧: ASP.NET页面跳转1.response.redirect 这个跳转页面的方法跳转的速度不快,因为它 ...
随机推荐
- 10倍性能提升!DLA SQL推出基于Alluxio的数据湖分析加速功能
简介: 在存储计算分离的场景下,通过网络从远端存储读取数据是一个代价较大的操作,往往会带来性能的损耗.以OSS为例,OSS数据读取延时通常较本地磁盘大很多,同时OSS对单个用户使用的带宽上限做了限制, ...
- iLogtail 与Filebeat 性能对比
简介:前段时间, iLogtail 阿里千万实例可观测采集器开源,其中介绍了iLogtail采集性能可以达到单核100MB/s,相比开源采集Agent有5-10倍性能优势.很多小伙伴好奇iLogta ...
- dotnet 8 破坏性改动 在 AssemblyInformationalVersionAttribute 添加上 git 的 commit 号
我在一个 WPF 项目里面,在界面显示应用的版本号,更新到 dotnet 8 的 SDK 之后,发现我的界面布局损坏了.本质上这个破坏性改动和 WPF 没有什么关系,是 dotnet 的 SDK 或编 ...
- dotnet 根据基线包版本实现库版本兼容
本文来告诉大家如何根据 基线包版本 的功能来实现自动在构建过程中,告诉开发者,当前版本是否存在不兼容旧版本的变更.其不兼容变更包括二进制中断变更和 API 不兼容变更和源代码中断变更.可以让库开发者花 ...
- 使用 NestJS 和 qrcode.js 创建 QR 码生成器 API
前言 QR码(Quick Response Code)是一种二维码,于1994年开发.它能快速存储和识别数据,包含黑白方块图案,常用于扫描获取信息.QR码具有高容错性和快速读取的优点,广泛应用于广告. ...
- Codeforces Round #922 (Div. 2) ABCD
A. Brick Wall 很直白的贪心,显然就是全放横着的砖最优,每行中最多能放 \(\lfloor \dfrac{m}{2} \rfloor\) 个,答案为 \(n \cdot \lfloor \ ...
- C++ Grammar Focus
一.结构体 1.基础模板 struct Node { <变量类型1> 变量名1; <变量类型2> 变量名2; ... } <定义变量名1>,<定义变量名2&g ...
- htts证书申请
https://freessl.cn/ 教程: https://www.bilibili.com/video/BV1Ug411673P/?spm_id_from=333.337.search-card ...
- postgresql 自动类型转换
一.错误案例 1.赋值错误: ERROR druid.sql.Statement:149 - {conn-10005, pstmt-20005} execute error. UPDATE sys_p ...
- 如何使用Python和Plotly绘制3D图形
本文分享自华为云社区<Plotly绘制3D图形> ,作者:柠檬味拥抱. 在数据可视化领域,三维图形是一种强大的工具,可以展示数据之间的复杂关系和结构.Python语言拥有丰富的数据可视化库 ...