Les principes de mise en œuvre et les idées de Java implémentant le chiffrement du mode SSH sont partagés avec vous.
1. Principe de cryptage SSH
SSH indique d'abord le mot de passe de chiffrement asymétrique du serveur via un cryptage asymétrique, puis utilise le mot de passe de chiffrement que les deux parties connaissent déjà pour le cryptage et le déchiffrement, voir la figure ci-dessous:
Explication: Pourquoi devons-nous utiliser le chiffrement asymétrique et le cryptage symétrique dans SSH? À quoi sert-il? Est-ce sûr ou non? Ensuite, nous avons utilisé le cryptage symétrique, pourquoi avons-nous utilisé le cryptage asymétrique au début? D'un autre côté, puisque le cryptage asymétrique est utilisé, pourquoi le cryptage symétrique devrait-il être utilisé?
Le cryptage asymétrique doit passer le mot de passe aléatoire 256 bits généré par le client au serveur. Ensuite, pendant le processus de livraison, la clé publique est utilisée pour le chiffrement, de sorte que ce mot de passe crypté 256 bits est difficile à casser sur le réseau.
Le cryptage symétrique, car l'utilisation fréquente du cryptage asymétrique est un gaspillage de performances, SSH utilise un mot de passe de 256 bits comme mot de passe crypté lors du passage du nom d'utilisateur et du mot de passe ensuite. Je crois que tout le monde connaît la difficulté de craquer, et il y a 0 à 9 changements dans chaque bit.
Est-ce sûr? Je pense que c'est toujours très bon, et c'est facile à comprendre lorsqu'il est utilisé.
2. Mon principe de cryptage SSH
①, scénarios d'utilisation
Le projet que j'ai développé est le trading à terme en vrac, qui sert principalement des échanges, ce qui crée une demande que nous devons contrôler le cycle des échanges à l'aide de notre logiciel. En d'autres termes, notre projet a une porte dérobée pour contrôler le cycle du projet. Si l'échange utilise le cycle logiciel, s'il ne renouvelle pas et que le code de projet est déployé sur le serveur de quelqu'un d'autre, il nous sera difficile de le contrôler. Cependant, avec cette porte dérobée, le logiciel sera automatiquement arrêté après son expiration, nous ne nous inquiétons donc pas que l'échange ne nous donne pas d'argent.
②, méthode d'utilisation
Le code de projet que nous donnons à la transaction contient une porte dérobée, qui envoie une demande au service Web via le client WebService.
Après avoir reçu la demande, le service Web renvoie les informations nécessaires au client.
Dans le processus ci-dessus, une méthode de demande de chiffrement SSH sera générée. Veuillez me permettre d'utiliser un chiffre maladroit pour le représenter.
3. Mon implémentation SSH
Étant donné que vous souhaitez utiliser WebService, vous devez établir un service Web et un client de service Web. Je ne veux pas en dire trop à ce sujet pour le moment, il y a de nombreuses façons, donc je ne ferai pas d'induire tout le monde ici. Je l'ai fait via Eclipse, et je peux me référer à la communication entre les services Web.
Ensuite, je présenterai le code, mais compte tenu du problème de longueur, je ne publierai pas de codes inutiles. La clé est d'expliquer clairement ce principe.
①, service
ExchangeService.java
Byte public [] Request (String Param, String resultType) {logger.info ("Paramètre de demande:" + param); // return objet keyResult keyResult = new KeyResult (); essayez {// obtenez la clé publique d'abord if (resultType.equals (public_key_result_type)) {map <string, object> keymap = rsacoder.initkey (); // Générez les clés publiques et privées PrivateKey = rsacoder.getPrivateKey (keymap); keyResult.setKey (rsacoder.getPublicKey (keymap)); Logger.info ("String de clé publique:" + keyResult.getKey ()); Logger.info ("String de clé privée:" + privateKey); } else if (resultType.equals (echostr_result_type)) {// Définissez les informations du mot de passe du client Byte [] parambyte = new base64decoder (). decodeBuffer (param); eChostr = new String (rsacoder.decryptByPrivateKey (parambyte, privateKey)); } else {// Obtenez les informations d'autorisation correspondant à l'échange via la base de données. // Convertissez d'abord la demande en tableau d'octets, puis décryptez-le, et enfin le convertir en une chaîne ExchangeInfo info = ExchangeInfo.dao.getInfoByName (nouvelle chaîne (cryptutil.decrypt (new Base64Deccoder (). DecodeBuffer (param), eChostr.getBytes ()))); Résultat de chaîne = ""; // obtient les autorisations compatibles du système if (resultType.equals (privilège_result_type)) {// juge d'abord les autorisations d'utilisation // lors de la jugement de la date d'utilisation // Utilisation actuelle de la connexion pour obtenir la date actuelle et la date de début de la connexion à comparer, puis calculer les dates qui peuvent encore être utilisées à long terme (nouvelle date (). // Convertir en jours int day = (int) (temps / (60 * 60 * 24)); // Nombre de jours qui peuvent toujours être utilisés si (usagedays - jour> 0) {// Vous pouvez utiliser le résultat = "1"; } else {// vous ne pouvez pas utiliser le résultat = "0"; }} keyResult.setResult (cryptUtil.encrypt (result.getBytes (), echostr.getBytes ())); } return JSonUtil.ObjectToByte (KeyResult); } catch (exception e) {Logger.Error ("Erreur WebService !!!"); logger.error (e.getMessage (), e); } retourner null;}Permettez-moi de le développer:
Le contenu de la première déclaration de jugement est de générer les clés publiques et privées et de retourner la clé publique.
Le contenu de l'instruction du deuxième jugement consiste à enregistrer la chaîne aléatoire envoyée par le client. Cette étape est très critique. La chaîne aléatoire est d'abord chiffrée avec la clé publique, qui améliore considérablement la profondeur du cryptage.
Le contenu de l'instruction du troisième jugement consiste à crypter les autorisations du client via une chaîne aléatoire.
②, client
ExchangeUtil.java
public static boolean canrunforexchange (string resultType) {int i = 1; Résultat booléen = false; while (true) {try {// webService Calling classe ExchangeServiceProxy proxy = new ExchangeServiceProxy (); Base64Encoder Encoder = new Base64Encoder (); // Step1. Obtenez la clé publique générée par le service keyResult keyResult = jsonutil.bytetoObject (proxy.request (null, public_key_result_type), keyresult.class); // Step2. Générez une chaîne aléatoire et envoyez-la à WebSerivce String eChostr = strutil.getEchostryLength (10); octet [] echoByteParam = rsacoder.encryptByPublicKey (echostr.getbytes (), keyResult.getKey ()); proxy.request (Encoder.encode (echoByteParam), echostr_result_type); // Step3. Crypt les informations sur la demande du client et les envoyer à WebService // First Encrypt en tant que tableau d'octets, puis les convertir en un byte de chaîne [] Results = proxy.request (Encoder.encode (cryptutil.encrypt (constants.client_type.getbytes (), echostr.getbytes ()), résultat); keyResult = jsonutil.bytetoObject (résultats, keyResult.class); // Step4. Renvoie le message via un décryptage de mot de passe Response de chaîne du serveur = new String (cryptutil.decrypt (keyResult.getResult (), echostr.getbytes ())); if (réponse.equals ("1")) {result = true; } casser; } catch (exception e) {logger.debug ("th" + i + "Time Chargement webService a échoué"); i ++; logger.error (e.getMessage (), e); if (i> = 10) {break; }}} Retour Résultat;}Une brève explication:
La boucle est principalement pour empêcher le service d'envoyer des demandes en continu lorsque le réseau est déconnecté et jusqu'à 10 fois est suffisant.
Il y a quatre étapes principales, et ce que je veux expliquer dans les commentaires est OK.
③, cryptage partagé et décryptage des classes publiques
Cryptutil.java
Package com.honzh.socket.util; importer javax.crypto.cipher; import javax.crypto.secretkey; import javax.crypto.secretkeyfactory; import javax.crypto.spec.deskeyspec; importer javax.crypto.spe.ivParameterspecc; Classique publique crusptuil {** * * @Title: Encrypt * @Description: Encrypt * @param data * @param key * @return * @throws exception * / public static byte [] Encrypt (byte [] data, byte [] key) lève exception {key = get8 (key); Cipher Cipher = Cipher.getInstance ("DES / CBC / PKCS5PADDING"); DeskeySpec dekeyspec = new deskeyspec (clé); SecretKey KeyFactory = SecretKeyFactory.getInstance ("DES"); SecretKey SecretKey = KeyFactory.GeneraSECret (Deskeyspec); IvParameterspec IV = new ivParameterspec (key); cipher.init (cipher.encpt_mode, SecretKey, iv); return cipher.dofinal (données); } / ** * @Title: Decrypt * @Description: Decrypt * @param data * @param key * @return * @throws exception * / public static byte [] décrypt (byte [] data, byte [] key) lève exception {key = get8 (key); Cipher Cipher = Cipher.getInstance ("DES / CBC / PKCS5PADDING"); DeskeySpec dekeyspec = new deskeyspec (clé); SecretKeyFactory KeyFactory = SecretKeyFactory.getInstance ("DES"); SecretKey SecretKey = KeyFactory.GeneraSECret (Deskeyspec); IvParameterspec IV = new ivParameterspec (key); cipher.init (cipher.decrypt_mode, SecretKey, iv); return cipher.dofinal (données); } octet statique privé [] get8 (byte [] key) {byte [] key1 = new byte [8]; pour (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; }} D'une manière générale, le cryptage SHA et MD5 nous suffit à utiliser!
Quant aux autres catégories auxiliaires, je ne les présenterai pas beaucoup. Il existe de nombreuses ressources sur Internet et j'espère que tout le monde pourra apprendre en combinaison.