当前位置:网站首页>The foreground uses RSA asymmetric security to encrypt user information
The foreground uses RSA asymmetric security to encrypt user information
2022-07-03 12:45:00 【Persia_ Pepper】
First, simply clarify the difference between symmetric encryption and asymmetric encryption :
Symmetric encryption : That is, the same key is used for encryption and decryption ;
Asymmetric encryption : That is, generate two keys , Use public key for encryption , Decryption is using the private key ;
explain : The encryption operation of this practice mainly generates the following three key objects
1. Encryption module
2. Encrypt public key
3. Encrypt private key
Ideas : The function of public key is to encrypt the specified string ; The private key decrypts the specified string ; Every time the front desk sends http Requests to the background will be newly generated Encryption module 、 Encrypt public key 、 Encrypt private key , The public key and encryption module will be sent to the foreground to encrypt the data ; The private key is kept in the background waiting . After the current station uses public key encryption , Transfer data to the background , Then decrypt with the reserved private key .
Be careful : Every time I generate Encryption module 、 Encrypt public key 、 Encrypt private key They are all produced by combination , Not produced at the same time , The error that the packet decryption failed !
Now I will summarize all the encryption and decryption in the foreground and background , Be flexible according to the actual development situation :
Tool class : New tool class , For data conversion
public class HexUtil {
/** * Binary system byte Array to hex byte Array * byte array to hex * * @param b byte array * @return hex string */
public static String byte2hex(byte[] b) {
StringBuilder hs = new StringBuilder();
String stmp;
for (int i = 0; i < b.length; i++) {
stmp = Integer.toHexString(b[i] & 0xFF).toUpperCase();
if (stmp.length() == 1) {
hs.append("0").append(stmp);
} else {
hs.append(stmp);
}
}
return hs.toString();
}
/** * Hexadecimal byte Array to binary byte Array * hex to byte array * * @param hex hex string * @return byte array */
public static byte[] hex2byte(String hex)
throws IllegalArgumentException{
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException ("invalid hex string");
}
char[] arr = hex.toCharArray();
byte[] b = new byte[hex.length() / 2];
for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
String swap = "" + arr[i++] + arr[i];
int byteint = Integer.parseInt(swap, 16) & 0xFF;
b[j] = new Integer(byteint).byteValue();
}
return b;
}
public static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
}
The core :RSA Encryption class
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
/** * RSA Tool class . Provide encryption , Decrypt , Generate key peer method . * Need to download bcprov-jdk14-123.jar. * */
public class RSAUtils {
private static final int MAX_ENCRYPT_BLOCK = 117; // RSA Maximum encrypted clear text size
private static final int MAX_DECRYPT_BLOCK = 128; // RSA Maximum decryption ciphertext size
/** * Generate public and private keys * * @throws NoSuchAlgorithmException */
public static KeyPair genRSAKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
return keyPairGen.generateKeyPair();
}
/** * Use modules and exponents to generate RSA Public key * Be careful :【 This code uses the default filling method , by RSA/None/PKCS1Padding, Different JDK The default filling method may be different , Such as Android The default is RSA * /None/NoPadding】 * * @param modulus model * @param exponent Index * @return */
public static RSAPublicKey getPublicKey(String modulus, String exponent) {
try {
BigInteger b1 = new BigInteger(modulus, 16);
BigInteger b2 = new BigInteger(exponent, 16);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/** * Use modules and exponents to generate RSA Private key * Be careful :【 This code uses the default filling method , by RSA/None/PKCS1Padding, Different JDK The default filling method may be different , Such as Android The default is RSA * /None/NoPadding】 * * @param modulus model * @param exponent Index * @return */
public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
try {
BigInteger b1 = new BigInteger(modulus, 16);
BigInteger b2 = new BigInteger(exponent, 16);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/** * Public key encryption */
public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.length;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
int offSet = 0;
byte[] cache;
int i = 0;
// Segment encryption of data
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
return out.toByteArray();
}
}
/** * Private key decryption */
public static String decryptByPrivateKey(byte[] encryptedData, RSAPrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
int inputLen = encryptedData.length;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
int offSet = 0;
byte[] cache;
int i = 0;
// Segment decryption of data
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
return new String(out.toByteArray(), "utf-8");
}
}
/** * ASCII Transcoding BCD code */
public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
byte[] bcd = new byte[asc_len / 2];
int j = 0;
for (int i = 0; i < (asc_len + 1) / 2; i++) {
bcd[i] = asc_to_bcd(ascii[j++]);
bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
}
return bcd;
}
public static byte asc_to_bcd(byte asc) {
byte bcd;
if ((asc >= '0') && (asc <= '9'))
bcd = (byte) (asc - '0');
else if ((asc >= 'A') && (asc <= 'F'))
bcd = (byte) (asc - 'A' + 10);
else if ((asc >= 'a') && (asc <= 'f'))
bcd = (byte) (asc - 'a' + 10);
else
bcd = (byte) (asc - 48);
return bcd;
}
/** * BCD Turn the string */
public static String bcd2Str(byte[] bytes) {
char temp[] = new char[bytes.length * 2], val;
for (int i = 0; i < bytes.length; i++) {
val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
val = (char) (bytes[i] & 0x0f);
temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
}
return new String(temp);
}
/** * Split string */
public static String[] splitString(String string, int len) {
int x = string.length() / len;
int y = string.length() % len;
int z = 0;
if (y != 0) {
z = 1;
}
String[] strings = new String[x + z];
String str = "";
for (int i = 0; i < x + z; i++) {
if (i == x + z - 1 && y != 0) {
str = string.substring(i * len, i * len + y);
} else {
str = string.substring(i * len, i * len + len);
}
strings[i] = str;
}
return strings;
}
/** * split array */
public static byte[][] splitArray(byte[] data, int len) {
int x = data.length / len;
int y = data.length % len;
int z = 0;
if (y != 0) {
z = 1;
}
byte[][] arrays = new byte[x + z][];
byte[] arr;
for (int i = 0; i < x + z; i++) {
arr = new byte[len];
if (i == x + z - 1 && y != 0) {
System.arraycopy(data, i * len, arr, 0, y);
} else {
System.arraycopy(data, i * len, arr, 0, len);
}
arrays[i] = arr;
}
return arrays;
}
//String Decrypt
public static String Decrypt(String str,String mou,String m) throws Exception{
// model hex
String modulus =mou;
// Private key index hex
String private_exponent = m;
RSAPrivateKey priKey = getPrivateKey(modulus, private_exponent);
return decryptByPrivateKey(HexUtil.hexStringToBytes(str), priKey);
}
// Get module information
public static Map getModulus () throws NoSuchAlgorithmException{
KeyPair keyPair = genRSAKeyPair();
Map map = new HashMap();
// Generate public and private keys
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// model hex
String modulus = publicKey.getModulus().toString(16);
// Public key index hex
String public_exponent = publicKey.getPublicExponent().toString(16);
// Private key index hex
String private_exponent = privateKey.getPrivateExponent().toString(16);
map.put("g", public_exponent);
map.put("m", private_exponent);
map.put("modu", modulus);
return map;
}
public static void main(String[] args) throws Exception {
KeyPair keyPair = genRSAKeyPair();
// Generate public and private keys
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// model hex
String modulus = publicKey.getModulus().toString(16);
// Public key index hex
String public_exponent = publicKey.getPublicExponent().toString(16);
// Private key index hex
String private_exponent = privateKey.getPrivateExponent().toString(16);
System.out.println("public_modulus: " + modulus);
System.out.println("public_exponent: " + public_exponent);
System.out.println("private_exponent: " + private_exponent);
// Plaintext
String plaintStr = "123456";
System.out.println("plaintStr: " + plaintStr);
// Use modulus and exponent to generate public and private keys
RSAPublicKey pubKey = getPublicKey(modulus, public_exponent);
RSAPrivateKey priKey = getPrivateKey(modulus, private_exponent);
// Ciphertext after public key encryption
byte[] encryptStr = encryptByPublicKey(plaintStr.getBytes("utf-8"), pubKey);
System.out.println("encryptStr: " + HexUtil.bytesToHexString(encryptStr));
String jmh = HexUtil.bytesToHexString(encryptStr);
System.out.println("start");
// Plaintext after decryption of private key
System.out.println("decryptStr: " + decryptByPrivateKey(HexUtil.hexStringToBytes(jmh), priKey));
}
}
Business logic class 1
// Declare the encryption key
private static String m;
// Declare the encryption module
private static String mou;
//2
// call RSA The utility class getModulus Method to obtain the matching public key , Secret key , And encryption module information , And send the public key and encryption module to the foreground , Secret key and encryption module
// Save to the background
@ResponseBody
@RequestMapping(value = "/getMoudle", method = RequestMethod.POST)
public Object getMoudle() throws NoSuchAlgorithmException {
Map jmInfo = RSAUtils.getModulus();
String my = jmInfo.getString("m");
m = my;
mou = jmInfo.getString("modu");
return jmInfo;
}
JS Page send request
//1
// Reflect js package
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn2.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/prng4.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/rng.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/rsa.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/rsa2.js"></script>
//2 Declare encrypted objects
var RSADo = {
"modulus":"",
"publicExponent":""}
//3 Get encrypted information
$(function() {
$("#denglu").bind("click", function() {
$.ajax("/..../....",{
data :{
},
dataType: 'json', // Server return json Format data
async: false,
type: 'post', //HTTP Request type
timeout: 10000, // Timeout set to 10 second ;
success: function (data) {
RSADo.modulus = data.modu;
RSADo.publicExponent = data.g;
//privateKey = data.m;
var userName = $("#userName").val();
var possWord = $("#iptPwd").val();
// Encrypt with the obtained public key
var rsa = new RSAKey();
rsa.setPublic(RSADo.modulus, RSADo.publicExponent);
var Name = rsa.encrypt(userName);
var pwd = rsa.encrypt(possWord);
console.log(' After encryption (name):', Name);
console.log(' After encryption (pwd):', pwd);
// Private key decryption
// Usually, you won't get the private key and decrypt it in the foreground , Just list this situation
//rsa.setPrivate(RSADo.modulus, RSADo.publicExponent, privateKey)
//var decryptStr = rsa.decrypt(encryptStr)
//console.log(' Decrypt private key :', privateKey)
//console.log(' After decryption (decrypt)', decryptStr)
// The current account password is set to RSA Encrypted state , Otherwise, the plaintext will still be exposed
$('#userName').val(Name);
$('#iptPwd').val(pwd);
// Execute the submit function , Go backstage again
$('#form').submit();
},
error: function (xhr, type, errorThrown) {
}
});
});
// Declare the public key encryption method
function encryption(str){
// Instantiation js Of RSA Object to generate
var rsa = new RSAKey()
rsa.setPublic(RSADo.modulus, RSADo.publicExponent)
var encryptStr = rsa.encrypt(str);
return encryptStr;
}
Part of the relatively old framework , It is possible to directly put the business logic class into the encryption class and execute it together
Notice the static properties of this declaration , Used to store keys and encryption modules
Some framework requests cannot simply throw exceptions for foreground requests, but catch exceptions , And the return type needs to be encapsulated into json The string returns without error , There are many strange problems
// Declare the encryption key
private static String m;
// Declare the encryption module
private static String mou;
@Action
public String getModule() {
Map jmInfo = new HashMap();
try {
jmInfo = MainPage.getModulus();
String my = jmInfo.get("m").toString();
m = my;
mou = jmInfo.get("modu").toString();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONObject json = new JSONObject();
json.putAll(jmInfo);
return json.toString();
}
Corresponding to the above main Method a summary of all the information , Make another simplification
public static void main(String[] args) throws Exception {
HttpServletRequest req = ActionContext.getActionContext().getHttpServletRequest();
HttpServletResponse resp = ActionContext.getActionContext().getHttpServletResponse();
String userName = req.getParameter(System.getProperty( user name ));
String possWord = req.getParameter(System.getProperty( password ));
// Make an account 、 Non empty judgment of password
if(!StringUtility.isNullOrEmpty(userName) && !StringUtility.isNullOrEmpty(possWord)) {
// Usually , We don't need to do it again getMoudles() Method to establish the key
// The static attributes stored above should be applied directly ( Private key --m, Encryption module --mou)
// Otherwise, the decryption failure error will appear , Because creating again is two sets of keys
// Generate private key using modulus and exponent
RSAPrivateKey priKey = getPrivateKey(mou, m);
System.out.println(" Start decrypting ");
// Plaintext after decryption of private key
System.out.println("decryptName: " + decryptByPrivateKey(HexUtil.hexStringToBytes(Name), priKey));
System.out.println("decryptPwd: " + decryptByPrivateKey(HexUtil.hexStringToBytes(Pwd), priKey));
String decryptName = decryptByPrivateKey(HexUtil.hexStringToBytes(userName), priKey);
String decryptPwd = decryptByPrivateKey(HexUtil.hexStringToBytes(possWord), priKey);
// Then take the decrypted account password , This verification verifies , If you pass, you can log in
}
}
This summary is more detailed , It mainly specifies the production of a set of keys , Then you can encrypt and decrypt in this set of keys , If you are in the main program again new A set of keys , That's absolutely unmatched .
Of course, in most cases, the foreground requests to obtain Encryption module and public key , and Private key and encryption module Is saved in the defined static attribute ; When logging in, send the data to the background for confirmation , Directly call the static attribute to decrypt ; The article summarizes that the encryption and decryption of all situations is also for the diversity of situations , In case of need ~
边栏推荐
- 雲計算未來 — 雲原生
- Adult adult adult
- Sqoop1.4.4原生增量导入特性探秘
- The solution to change the USB flash disk into a space of only 2m
- T430 toss and install OS majave 10.14
- 最新版盲盒商城thinkphp+uniapp
- CNN MNIST handwriting recognition
- 【计网】第三章 数据链路层(2)流量控制与可靠传输、停止等待协议、后退N帧协议(GBN)、选择重传协议(SR)
- How to stand out quickly when you are new to the workplace?
- 2.6 preliminary cognition of synergetic couroutines
猜你喜欢

低代码平台国际化多语言(i18n)技术方案

The latest version of blind box mall thinkphp+uniapp

Application of ncnn neural network computing framework in orange school orangepi 3 lts development board

Alibaba is bigger than sending SMS (user microservice - message microservice)

剑指Offer05. 替换空格

Day 1 of kotlin learning: simple built-in types of kotlin

公纵号发送提示信息(用户微服务--消息微服务)
![Sword finger offer04 Search in two-dimensional array [medium]](/img/c4/002c951f8d914aaea4f4133685ebd1.png)
Sword finger offer04 Search in two-dimensional array [medium]

【计网】第三章 数据链路层(2)流量控制与可靠传输、停止等待协议、后退N帧协议(GBN)、选择重传协议(SR)

最新版盲盒商城thinkphp+uniapp
随机推荐
Do you feel like you've learned something and forgotten it?
ncnn神经网络计算框架在香橙派OrangePi 3 LTS开发板中的使用介绍
It feels great to know you learned something, isn‘t it?
Use bloc to build a page instance of shutter
Redhat5 installing socket5 proxy server
alright alright alright
Bert running error: attributeerror: module'tensorflow contrib. tpu' has no attribute 'InputPipelineConfig'
4. Wireless in vivo nano network: electromagnetic propagation model and key points of sensor deployment
LeetCode 0556. Next bigger element III - end of step 4
Swift bit operation exercise
【ArcGIS自定义脚本工具】矢量文件生成扩大矩形面要素
The best shortcut is no shortcut
Swift5.7 扩展 some 到泛型参数
The latest version of lottery blind box operation version
2.9 overview of databinding knowledge points
Take you to the installation and simple use tutorial of the deveco studio compiler of harmonyos to create and run Hello world?
初入职场,如何快速脱颖而出?
强大的头像制作神器微信小程序
【综合题】【数据库原理】
01_ Using the concurrent tool class library, is thread safety safe