I believe many people use SSH remote connection to Linux, then for our user name and password, SSH is how to encrypt and decrypt it? After the discussion with colleagues, and gradually understand the principle of encryption, the following one by one elaborated:
Encryption principle
SSH is the first through the asymmetric encryption to tell the server a symmetric encryption password, and then to verify the user name and password, using the encrypted password that both parties already know to encrypt and decrypt, see:
Explanation: Why is it useful to use asymmetric encryption and symmetric encryption in SSH? How safe is it? Since symmetric encryption was used later, why use asymmetric encryption at the beginning? Conversely, since asymmetric encryption is used, why is symmetric encryption used again?
- Asymmetric encryption is to pass the 256-bit random password generated by the client to the server, then in the process of delivery, the use of the public key is encrypted, so that the 256-bit encryption password is difficult to be cracked on the network.
- Symmetric encryption, because the frequent use of asymmetric encryption is very wasteful performance, then SSH is a 256-bit length of password as the next pass the user name password encryption password, its crack difficult, presumably everyone knows, each has 0-9 kinds of changes.
- This is safe, I think it is very good, specific use is also easy to understand.
Well, next into the actual operation, I'm using the Java language,
First, you copy the following code snippet.
' Package com.honzh.socket.base.rsa;
Import Java.security.MessageDigest;
Import Javax.crypto.KeyGenerator;
Import Javax.crypto.Mac;
Import Javax.crypto.SecretKey;
Import Javax.crypto.spec.SecretKeySpec;
Import Sun.misc.BASE64Decoder;
Import Sun.misc.BASE64Encoder;
/**
* Basic Cryptographic components
*
* @author Present
* @version 1.0
* @since 1.0
*/
Public abstract class Coder {
public static final String Key_sha = "SHA";
public static final String key_md5 = "MD5";
/** * Mac algorithm can choose the following algorithms * * <pre> * HmacMD5 * HmacSHA1 * HmacSHA256 * HmacSHA384 * HmacSHA512 * </pre> */PUBL IC static final String Key_mac = "HmacMD5";/** * BASE64 decryption * * @param KEY * @return * @throws Exception */public static by Te[] decryptBASE64 (String key) throws Exception {return (new Base64decoder ()). Decodebuffer (key);} /** * BASE64 Encryption * * @param key * @return * @throws Exception */public static String encryptBASE64 (byte[] key) throws Excep tion {return (new Base64encoder ()). Encodebuffer (key);} /** * MD5 Encryption * * @param data * @return * @throws Exception */public static byte[] EncryptMD5 (byte[) data) throws Exception {MessageDigest MD5 = messagedigest.getinstance (KEY_MD5); Md5.update (data); return Md5.digest ();} /** * SHA Encryption * * @param data * @return * @throws Exception */public static byte[] Encryptsha (byte[) data) throws Exception {MessageDigest sha = messagedigest.getinstance (Key_sha); Sha.update (data); return Sha.digest ();} /** * Initialize HMAC key * * @return * @throws Exception */public static String Initmackey () throws Exception {Keygenerator Keygenerator = Keyg Enerator.getinstance (KEY_MAC); Secretkey Secretkey = Keygenerator.generatekey (); Return encryptBASE64 (secretkey.getencoded ());} /** * HMAC Encryption * * @param data * @param key * @return * @throws Exception */public static byte[] Encrypthmac (byte[) data, S Tring key) throws Exception {Secretkey Secretkey = new Secretkeyspec (decryptBASE64 (key), KEY_MAC); Mac Mac = Mac.getinstance (Secretkey.getalgorithm ()); Mac.init (Secretkey); return mac.dofinal (data);}
}
Package Com.honzh.socket.base.rsa;
public class Keyresult {
Private String key;
Private byte[] result;
Private String signstr;
public String getKey() { return key;}public void setKey(String key) { this.key = key;}public byte[] getResult() { return result;}public void setResult(byte[] result) { this.result = result;}/** * @return the signStr */public String getSignStr() { return signStr;}/** * @param signStr the signStr to set */public void setSignStr(String signStr) { this.signStr = signStr;}
}
Package Com.honzh.socket.base.rsa;
Import Java.security.Key;
Import Java.security.KeyFactory;
Import Java.security.KeyPair;
Import Java.security.KeyPairGenerator;
Import Java.security.PrivateKey;
Import Java.security.PublicKey;
Import Java.security.Signature;
Import Java.security.interfaces.RSAPrivateKey;
Import Java.security.interfaces.RSAPublicKey;
Import Java.security.spec.PKCS8EncodedKeySpec;
Import Java.security.spec.X509EncodedKeySpec;
Import Java.util.HashMap;
Import Java.util.Map;
Import Javax.crypto.Cipher;
/**
* RSA Secure Encoding Component
*
* @author Present
* @version 1.0
* @since 1.0
*/
Public abstract class Rsacoder extends coder {
public static final String key_algorithm = "RSA";
public static final String signature_algorithm = "Md5withrsa";
private static final String Public_key = "Rsapublickey";p rivate static final String private_key = "Rsaprivatekey";/** * Private Key pair information generates a digital signature * * @param data * encryption * @param privatekey * Private Key * * @return * @throws Exception */publi c static string sign (byte[] data, String privatekey) throws Exception {//Decrypt private key base64 encoded by byte[] Keybytes = DECRYPTB ASE64 (Privatekey); Constructs the Pkcs8encodedkeyspec object Pkcs8encodedkeyspec pkcs8keyspec = new Pkcs8encodedkeyspec (keybytes); Key_algorithm the specified cryptographic algorithm keyfactory keyfactory = keyfactory.getinstance (key_algorithm); Take the private key object Privatekey Prikey = Keyfactory.generateprivate (Pkcs8keyspec); Generate digital signatures for information with the private key Signature Signature = Signature.getinstance (signature_algorithm); Signature.initsign (Prikey); Signature.update (data); Return encryptBASE64 (Signature.sign ());} /** * Verify the digital signature * * @param data * encryption * @param publickey * Public key * @param sign * Digital signature * * @r Eturn Verify Success Returns TRUE Failure returns false *@throws Exception * */public static Boolean verify (byte[] data, string publickey, String sign) throws Exception { Decrypt the public key encoded by base64 byte[] Keybytes = decryptBASE64 (PublicKey); Constructs the X509encodedkeyspec object X509encodedkeyspec keySpec = new X509encodedkeyspec (keybytes); Key_algorithm the specified cryptographic algorithm keyfactory keyfactory = keyfactory.getinstance (key_algorithm); Take the public key object PublicKey PubKey = Keyfactory.generatepublic (KeySpec); Signature Signature = signature.getinstance (signature_algorithm); Signature.initverify (PubKey); Signature.update (data); Verify that the signature is normal return signature.verify (decryptBASE64 (sign));} /** * Decrypt <br> * Decrypt with private key * * @param data * @param key * @return * @throws Exception */public static byte[] Decryptbypri Vatekey (byte[] data, String key) throws Exception {//Decrypt the key byte[] keybytes = decryptBASE64 (key); Obtain the private key pkcs8encodedkeyspec Pkcs8keyspec = new Pkcs8encodedkeyspec (keybytes); Keyfactory keyfactory = keyfactory.gEtinstance (Key_algorithm); Key Privatekey = keyfactory.generateprivate (Pkcs8keyspec); Decrypt the data Cipher Cipher = Cipher.getinstance (Keyfactory.getalgorithm ()); Cipher.init (Cipher.decrypt_mode, Privatekey); return cipher.dofinal (data);} /** * Decrypt <br> * Decrypt with public key * * @param data * @param key * @return * @throws Exception */public static byte[] Decryptbypub Lickey (byte[] data, String key) throws Exception {//Decrypt the key byte[] keybytes = decryptBASE64 (key); Get the public key x509encodedkeyspec X509keyspec = new X509encodedkeyspec (keybytes); Keyfactory keyfactory = keyfactory.getinstance (key_algorithm); Key PublicKey = Keyfactory.generatepublic (X509keyspec); Decrypt the data Cipher Cipher = Cipher.getinstance (Keyfactory.getalgorithm ()); Cipher.init (Cipher.decrypt_mode, PublicKey); return cipher.dofinal (data);} /** * Encrypt <br> * Encrypt with public key * * @param data * @param key * @return * @throws Exception */public static byte[] Encryptbypub Lickey (byte[] data, String key) Throws Exception {//Decrypt the public key byte[] keybytes = decryptBASE64 (key); Get the public key x509encodedkeyspec X509keyspec = new X509encodedkeyspec (keybytes); Keyfactory keyfactory = keyfactory.getinstance (key_algorithm); Key PublicKey = Keyfactory.generatepublic (X509keyspec); Encrypt the data Cipher Cipher = Cipher.getinstance (Keyfactory.getalgorithm ()); Cipher.init (Cipher.encrypt_mode, PublicKey); return cipher.dofinal (data);} /** * Encrypt <br> * Encrypt with private key * * @param data * @param key * @return * @throws Exception */public static byte[] Encryptbypri Vatekey (byte[] data, String key) throws Exception {//Decrypt the key byte[] keybytes = decryptBASE64 (key); Obtain the private key pkcs8encodedkeyspec Pkcs8keyspec = new Pkcs8encodedkeyspec (keybytes); Keyfactory keyfactory = keyfactory.getinstance (key_algorithm); Key Privatekey = keyfactory.generateprivate (Pkcs8keyspec); Encrypt the data Cipher Cipher = Cipher.getinstance (Keyfactory.getalgorithm ()); Cipher.init (Cipher.encrypt_mode, Privatekey); return cipher.dofinal (data);} /** * Get the private key * * @param keyMap * @return * @throws Exception */public static String Getprivatekey (map<string, object> KEYMAP) throws Exception {key key = (key) keymap.get (Private_key); Return encryptBASE64 (key.getencoded ());} /** * Get Public key * * @param keyMap * @return * @throws Exception */public static String Getpublickey (map<string, object> KEYMAP) throws Exception {key key = (key) keymap.get (Public_key); Return encryptBASE64 (key.getencoded ());} /** * Initialize Key * * @return * @throws Exception */public static map<string, object> Initkey () throws Exception {Key Pairgenerator Keypairgen = keypairgenerator. getinstance (Key_algorithm); Keypairgen.initialize (1024); KeyPair KeyPair = Keypairgen.generatekeypair (); Public key Rsapublickey PublicKey = (rsapublickey) keypair.getpublic (); Private key Rsaprivatekey Privatekey = (rsaprivatekey) keypair.getprivate (); Map<string, object> KeyMap = new hashmap<string, object> (2); Keymap.put (Public_key, PublicKey); Keymap.put (Private_key, Privatekey); return KEYMAP;}
}
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: Encryption
* @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);
Secretkeyfactory 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: 解密* @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;}
}
`
Use WebService for communication
WebService, I will no longer do the demo code, to focus on how the SSH principle of the client and server between the request and corresponding.
1. Generate the corresponding public and private keys on the server side
Map<String, Object> keyMap = RSACoder.initKey(); // 产生公钥和私钥 privateKey = RSACoder.getPrivateKey(keyMap); keyResult.setKey(RSACoder.getPublicKey(keyMap)); logger.info("公钥字符串:" + keyResult.getKey()); logger.info("私钥字符串:" + privateKey);
2. The client obtains the corresponding public key
KeyResult keyResult = (KeyResult) JsonUtil.byteToObject(proxy.request(null, PUBLIC_KEY_RESULT_TYPE), KeyResult.class);
3. The client generates a random string and sends it to WEBSERIVCE
String echoStr = getEchoStrByLength(10); byte[] echoByteParam = RSACoder.encryptByPublicKey(echoStr.getBytes(), keyResult.getKey()); proxy.request(encoder.encode(echoByteParam), ECHOSTR_RESULT_TYPE);
4. Get the password on the server and save it
// 设置客户端的口令信息 bytenew BASE64Decoder().decodeBuffer(param); new String(RSACoder.decryptByPrivateKey(paramByte, privateKey));
5. The client encrypts the client request information and then sends it to WebService, first encrypted to a byte array, and then converted to a string
byte[] results = proxy.request( encoder.encode(CryptUtil.encrypt(CLIENT_TYPE.getBytes(), echoStr.getBytes())), resultType); keyResult = (KeyResult) JsonUtil.byteToObject(results, KeyResult.class);
6. After the server has received the corresponding request, the corresponding decryption processing, the request is converted to a byte array, and then decrypted, and finally converted to a string
ExchangeInfo info = ExchangeInfo.dao.getInfoByName(new String(CryptUtil.decrypt( new BASE64Decoder().decodeBuffer(param), echoStr.getBytes())));
and return the data through symmetric encryption.
keyResult.setResult(CryptUtil.encrypt(result.getBytes(), echoStr.getBytes()));
7. After the client obtains the data, carries on the corresponding decryption processing
new String(CryptUtil.decrypt(keyResult.getResult(), echoStr.getBytes()));
Summary : The first time to use markdown write so much, is really tired ah, feel not cool enough.
Cryptographic features that enable SSH logins