当前位置:网站首页>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 ~
边栏推荐
- Low code platform international multilingual (I18N) technical solution
- Is it OK to open an account for online stock speculation? Is the fund safe?
- Sqoop1.4.4原生增量导入特性探秘
- Airflow installation jump pit
- Solve the problem of VI opening files with ^m at the end
- T430 toss and install OS majave 10.14
- 并网-低电压穿越与孤岛并存分析
- The latest version of blind box mall thinkphp+uniapp
- Ten workplace rules
- Self made pop-up input box, input text, and click to complete the event.
猜你喜欢
剑指Offer04. 二维数组中的查找【中等】
Self made pop-up input box, input text, and click to complete the event.
剑指Offer10- I. 斐波那契数列
Attack and defense world mobile--ph0en1x-100
强大的头像制作神器微信小程序
【ManageEngine】IP地址扫描的作用
最新版抽奖盲盒运营版
(latest version) WiFi distribution multi format + installation framework
Application of ncnn Neural Network Computing Framework in Orange Pi 3 Lts Development Board
Application of ncnn neural network computing framework in orange school orangepi 3 lts development board
随机推荐
If you can't learn, you have to learn. Jetpack compose writes an im app (I)
2.6 preliminary cognition of synergetic couroutines
启用MemCached的SASL认证
studio All flavors must now belong to a named flavor dimension. Learn more
Bert running error: attributeerror: module'tensorflow contrib. tpu' has no attribute 'InputPipelineConfig'
Simple use and precautions of kotlin's array array and set list
Everything comes to him who waits
Redhat5 installing socket5 proxy server
Implement verification code verification
【ArcGIS自定义脚本工具】矢量文件生成扩大矩形面要素
How to stand out quickly when you are new to the workplace?
Is it OK to open an account for online stock speculation? Is the fund safe?
Sword finger offer06 Print linked list from end to end
最新版抽奖盲盒运营版
Sword finger offer04 Search in two-dimensional array [medium]
Sword finger offer10- I. Fibonacci sequence
adb push apk
The difference between lambda and anonymous inner class
Swift Error Handling
Ali & ant self developed IDE