The implementation principles and ideas of Java implementing SSH mode encryption are shared with you.
1. SSH encryption principle
SSH first tells the server asymmetric encryption password through asymmetric encryption, and then uses the encryption password that both parties already know for encryption and decryption, see the figure below:
Explanation: Why do we need to use asymmetric encryption and symmetric encryption in SSH? What is the use of it? Is it safe or not? Then we used symmetric encryption, why did we use asymmetric encryption at the beginning? On the other hand, since asymmetric encryption is used, why should symmetric encryption be used?
Asymmetric encryption is to pass the 256-bit random password generated by the client to the server. Then, during the delivery process, the public key is used for encryption, so that this 256-bit encrypted password is difficult to crack on the network.
Symmetric encryption, because frequent use of asymmetric encryption is a waste of performance, SSH uses a 256-bit length password as the encrypted password when passing the username and password next. I believe everyone knows the difficulty of cracking, and there are 0-9 changes in each bit.
Is this safe? I think it is still very good, and it is easy to understand when used.
2. My SSH encryption principle
①, usage scenarios
The project I developed is bulk futures trading, which mainly serves exchanges, which creates a demand that we need to control the cycle of exchanges using our software. In other words, our project has a backdoor to control the project cycle. If the exchange uses the software cycle, if it does not renew and the project code is deployed on someone else's server, it will be difficult for us to control it. However, with this backdoor, the software will be automatically stopped after it expires, so we don't worry that the exchange will not give us money.
②, usage method
The project code we give the transaction contains a backdoor, which sends a request to the web service through the webservice client.
After receiving the request, the web service returns the information needed by the client.
In the above process, an SSH encryption request method will be generated. Please allow me to use a clumsy figure to represent it.
3. My SSH implementation
Since you want to use webservice, you need to establish a web service service and a web service client. I don’t want to say too much about this for the time being, there are many ways, so I won’t mislead everyone here. I did it through eclipse, and I can refer to the communication between the webservices.
Next, I will introduce the code, but considering the length issue, I will not post some unnecessary codes. The key is to explain this principle clearly.
①, service
ExchangeService.java
public byte[] request(String param, String resultType) { logger.info("Request parameter:" + param); // Return object KeyResult keyResult = new KeyResult(); try { // Get the public key first if (resultType.equals(PUBLIC_KEY_RESULT_TYPE)) { Map<String, Object> keyMap = RSACoder.initKey(); // Generate the public and private keys privateKey = RSACoder.getPrivateKey(keyMap); keyResult.setKey(RSACoder.getPublicKey(keyMap)); logger.info("Public key string: " + keyResult.getKey()); logger.info("Private key string: " + privateKey); } else if (resultType.equals(ECHOSTR_RESULT_TYPE)) { // Set the password information of the client byte[] paramByte = new BASE64Decoder().decodeBuffer(param); echoStr = new String(RSACoder.decryptByPrivateKey(paramByte, privateKey)); } else { // Get the permission information corresponding to the exchange through the database. // First convert the request to a byte array, then decrypt it, and finally convert it to a string ExchangeInfo info = ExchangeInfo.dao.getInfoByName(new String(CryptUtil.decrypt( new BASE64Decoder().decodeBuffer(param), echoStr.getBytes()))); String result = ""; // Get the system enabled permissions if (resultType.equals(PRIVILEGE_RESULT_TYPE)) { // First judge the usage permissions// When judging the usage date// Current login use to get the current date and start date of the login to compare, and then calculate the dates that can still be used long time = (new Date().getTime() / 1000) - string2DateInt(openday); // Convert to days int day = (int) (time / (60 * 60 * 24)); // Number of days that can still be used if (usedays - day > 0) { // You can use result = "1"; } else { // You cannot use result = "0"; } } keyResult.setResult(CryptUtil.encrypt(result.getBytes(), echoStr.getBytes())); } return JsonUtil.objectToByte(keyResult); } catch (Exception e) { logger.error("Webservice error!!!"); logger.error(e.getMessage(), e); } return null;}Let me elaborate on it:
The content in the first judgment statement is to generate the public and private keys and return the public key.
The content in the second judgment statement is to save the random string sent by the client. This step is very critical. The random string is first encrypted with the public key, which greatly enhances the depth of encryption.
The content in the third judgment statement is to encrypt the client's permissions through a random string.
②, client
ExchangeUtil.java
public static boolean canRunForExchange(String resultType) { int i = 1; boolean result = false; while (true) { try { // webservice calling class ExchangeServiceProxy proxy = new ExchangeServiceProxy(); BASE64Encoder encoder = new BASE64Encoder(); // step1. Get the public key generated by the service KeyResult keyResult = JsonUtil.byteToObject(proxy.request(null, PUBLIC_KEY_RESULT_TYPE), KeyResult.class); // step2. Generate a random string and send it to webserivce String echoStr = StrUtil.getEchoStrByLength(10); byte[] echoByteParam = RSACoder.encryptByPublicKey(echoStr.getBytes(), keyResult.getKey()); proxy.request(encoder.encode(echoByteParam), ECHOSTR_RESULT_TYPE); // step3. Encrypt the client request information and send it to webservice // First encrypt as a byte array, and then convert it into a string byte[] results = proxy.request( encoder.encode(CryptUtil.encrypt(Constants.client_type.getBytes(), echoStr.getBytes())), resultType); keyResult = JsonUtil.byteToObject(results, KeyResult.class); // step4. Return message through password decryption server String response = new String(CryptUtil.decrypt(keyResult.getResult(), echoStr.getBytes())); if (response.equals("1")) { result = true; } break; } catch (Exception e) { logger.debug("th" + i + "time loading webservice failed"); i++; logger.error(e.getMessage(), e); if (i >= 10) { break; } } } return result;}A brief explanation:
The loop is mainly to prevent the service from sending requests continuously when the network is disconnected, and up to 10 times is enough.
There are four main steps, and what I want to explain in the comments is OK.
③, Shared encryption and decryption of public classes
CryptUtil.java
package com.honzh.socket.util;import javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESKeySpec;import javax.crypto.spec.IvParameterSpec;public class CryptUtil { /** * @Title: encrypt * @Description: Encrypt* @param data * @param key * @return * @throws Exception */ public static byte[] encrypt(byte[] data, byte[] key) throws Exception { key = get8(key); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); DESKeySpec desKeySpec = new DESKeySpec(key); SecretKey keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = keyFactory.generateSecret(desKeySpec); IvParameterSpec iv = new IvParameterSpec(key); cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv); return cipher.doFinal(data); } /** * @Title: decrypt * @Description: Decrypt* @param data * @param key * @return * @throws Exception */ public static byte[] decrypt(byte[] data, byte[] key) throws Exception { key = get8(key); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); DESKeySpec desKeySpec = new DESKeySpec(key); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = keyFactory.generateSecret(desKeySpec); IvParameterSpec iv = new IvParameterSpec(key); cipher.init(Cipher.DECRYPT_MODE, secretKey, iv); return cipher.doFinal(data); } private static byte[] get8(byte[] key) { byte[] key1 = new byte[8]; for (int i = 0; i < 8; i++) { key1[i] = key[i]; } return key1; } public static String toHexString(byte[] data) { String s = ""; for (int i = 0; i < data.length; i++) { s += Integer.toHexString(data[i] & 0xFF)+"-"; } return s; }} Generally speaking, SHA and MD5 encryption are enough for us to use!
As for other auxiliary categories, I won’t introduce them much. There are many resources on the Internet, and I hope everyone can learn in combination.