หลักการการใช้งานและแนวคิดของการใช้การเข้ารหัสโหมด SSH ใช้ร่วมกับคุณ
1. หลักการการเข้ารหัส SSH
SSH บอกรหัสผ่านการเข้ารหัสแบบอสมมาตรครั้งแรกผ่านการเข้ารหัสแบบไม่สมมาตรจากนั้นใช้รหัสผ่านการเข้ารหัสที่ทั้งสองฝ่ายรู้สำหรับการเข้ารหัสและถอดรหัสดูรูปด้านล่าง:
คำอธิบาย: ทำไมเราต้องใช้การเข้ารหัสแบบไม่สมมาตรและการเข้ารหัสแบบสมมาตรใน SSH? การใช้งานของมันคืออะไร? ปลอดภัยหรือไม่? จากนั้นเราใช้การเข้ารหัสแบบสมมาตรทำไมเราถึงใช้การเข้ารหัสแบบอสมมาตรที่จุดเริ่มต้น? ในทางกลับกันเนื่องจากใช้การเข้ารหัสแบบไม่สมมาตรทำไมจึงควรใช้การเข้ารหัสแบบสมมาตร?
การเข้ารหัสแบบอสมมาตรคือการผ่านรหัสผ่านสุ่ม 256 บิตที่ไคลเอนต์สร้างขึ้นไปยังเซิร์ฟเวอร์ จากนั้นในระหว่างกระบวนการจัดส่งคีย์สาธารณะจะใช้สำหรับการเข้ารหัสเพื่อให้รหัสผ่านที่เข้ารหัส 256 บิตนี้ยากที่จะถอดรหัสบนเครือข่าย
การเข้ารหัสแบบสมมาตรเนื่องจากการใช้การเข้ารหัสแบบอสมมาตรบ่อยครั้งเป็นการเสียประสิทธิภาพ SSH ใช้รหัสผ่านความยาว 256 บิตเป็นรหัสผ่านที่เข้ารหัสเมื่อผ่านชื่อผู้ใช้และรหัสผ่านถัดไป ฉันเชื่อว่าทุกคนรู้ถึงความยากลำบากในการแตกและมีการเปลี่ยนแปลง 0-9 ในแต่ละบิต
ปลอดภัยหรือไม่? ฉันคิดว่ามันยังดีมากและเข้าใจง่ายเมื่อใช้
2. หลักการการเข้ารหัส SSH ของฉัน
①สถานการณ์การใช้งาน
โครงการที่ฉันพัฒนาขึ้นคือการซื้อขายล่วงหน้าจำนวนมากซึ่งส่วนใหญ่ทำหน้าที่แลกเปลี่ยนซึ่งสร้างความต้องการที่เราจำเป็นต้องควบคุมวัฏจักรของการแลกเปลี่ยนโดยใช้ซอฟต์แวร์ของเรา กล่าวอีกนัยหนึ่งโครงการของเรามีแบ็คดอร์เพื่อควบคุมวัฏจักรโครงการ หาก Exchange ใช้วัฏจักรซอฟต์แวร์หากไม่ต่ออายุและรหัสโครงการจะถูกปรับใช้กับเซิร์ฟเวอร์ของคนอื่นมันจะเป็นเรื่องยากสำหรับเราที่จะควบคุมมัน อย่างไรก็ตามด้วยแบ็คดอร์นี้ซอฟต์แวร์จะหยุดโดยอัตโนมัติหลังจากหมดอายุดังนั้นเราไม่ต้องกังวลว่าการแลกเปลี่ยนจะไม่ให้เงินกับเรา
②วิธีการใช้งาน
รหัสโครงการที่เราให้ธุรกรรมมีแบ็คดอร์ซึ่งส่งคำขอไปยังบริการเว็บผ่านไคลเอนต์ Webservice
หลังจากได้รับคำขอบริการเว็บจะส่งคืนข้อมูลที่ลูกค้าต้องการ
ในกระบวนการข้างต้นจะมีการสร้างวิธีการขอเข้ารหัส SSH โปรดอนุญาตให้ฉันใช้รูปซุ่มซ่ามเพื่อเป็นตัวแทน
3. การใช้งาน SSH ของฉัน
เนื่องจากคุณต้องการใช้ Webservice คุณต้องสร้างบริการเว็บบริการและไคลเอนต์บริการเว็บ ฉันไม่ต้องการพูดมากเกินไปเกี่ยวกับเรื่องนี้ในขณะนี้มีหลายวิธีดังนั้นฉันจะไม่ทำให้ทุกคนเข้าใจผิดที่นี่ ฉันทำผ่าน Eclipse และฉันสามารถอ้างถึงการสื่อสารระหว่าง Webservices
ต่อไปฉันจะแนะนำรหัส แต่เมื่อพิจารณาปัญหาความยาวฉันจะไม่โพสต์รหัสที่ไม่จำเป็น กุญแจสำคัญคือการอธิบายหลักการนี้อย่างชัดเจน
①, บริการ
ExchangeService.java
ไบต์สาธารณะ [] คำขอ (พารามิเตอร์สตริง, สตริงผลลัพธ์รีจิเนีย) {logger.info ("พารามิเตอร์คำขอ:" + พารามิเตอร์); // ส่งคืน Keyresult Keyresult = new Keyresult (); ลอง {// รับคีย์สาธารณะก่อนถ้า (resultType.equals (public_key_result_type)) {แผนที่ <สตริง, วัตถุ> keymap = rsacoder.initkey (); // สร้างคีย์สาธารณะและส่วนตัว PrivateKey = rsacoder.getPrivateKey (keymap); Keyresult.setKey (RSACODER.GETPUBLICKEY (KEYMAP)); logger.info ("คีย์สาธารณะสตริง:" + keyresult.getKey ()); logger.info ("สตริงคีย์ส่วนตัว:" + PrivateKey); } อื่นถ้า (resultType.equals (echostr_result_type)) {// ตั้งค่าข้อมูลรหัสผ่านของไคลเอนต์ไบต์ [] parambyte = ใหม่ base64decoder () DecodeBuffer (param); echosttr = สตริงใหม่ (rsacoder.decryptbyprivatekey (parambyte, privateKey)); } else {// รับข้อมูลการอนุญาตที่สอดคล้องกับการแลกเปลี่ยนผ่านฐานข้อมูล // ก่อนแปลงคำขอเป็นอาร์เรย์ไบต์จากนั้นถอดรหัสไว้และในที่สุดก็แปลงเป็นสตริง exchangeInfo info = exchangeInfo.dao.getInfobyname (สตริงใหม่ (cryptutil.decrypt (ใหม่ base64decoder () สตริงผลลัพธ์ = ""; // รับสิทธิ์ที่เปิดใช้งานระบบถ้า (ResultType.equals (privilege_result_type)) {// ก่อนตัดสินการอนุญาตการใช้งาน // ก่อนเมื่อตัดสินวันที่การใช้งาน // การเข้าสู่ระบบปัจจุบันใช้วันที่ปัจจุบัน // แปลงเป็นวัน int day = (int) (เวลา / (60 * 60 * 24)); // จำนวนวันที่ยังสามารถใช้งานได้หาก (ผู้ใช้งาน - วัน> 0) {// คุณสามารถใช้ผลลัพธ์ = "1"; } else {// คุณไม่สามารถใช้ผลลัพธ์ = "0"; }} keyresult.setResult (cryptutil.encrypt (result.getBytes (), echostr.getBytes ())); } return jsonutil.objectTobyte (Keyresult); } catch (exception e) {logger.error ("ข้อผิดพลาดของเว็บเซิร์ฟเวอร์ !!!"); logger.error (e.getMessage (), e); } return null;}ให้ฉันอธิบายอย่างละเอียด:
เนื้อหาในแถลงการณ์การตัดสินครั้งแรกคือการสร้างกุญแจสาธารณะและส่วนตัวและส่งคืนกุญแจสาธารณะ
เนื้อหาในคำสั่งการตัดสินครั้งที่สองคือการบันทึกสตริงสุ่มที่ส่งโดยลูกค้า ขั้นตอนนี้สำคัญมาก สตริงแบบสุ่มถูกเข้ารหัสครั้งแรกด้วยคีย์สาธารณะซึ่งช่วยเพิ่มความลึกของการเข้ารหัสอย่างมาก
เนื้อหาในคำสั่งการตัดสินครั้งที่สามคือการเข้ารหัสสิทธิ์ของลูกค้าผ่านสตริงแบบสุ่ม
②ลูกค้า
ExchangeUtil.java
บูลีนแบบคงที่สาธารณะ canrunforexchange (สตริงผลลัพธ์ ttype) {int i = 1; ผลลัพธ์บูลีน = false; ในขณะที่ (จริง) {ลอง {// webservice calling คลาส exchangeServiceProxy proxy = new ExchangeServiceProxy (); base64Encoder encoder = ใหม่ base64Encoder (); // step1 รับคีย์สาธารณะที่สร้างขึ้นโดย Service Keyresult Keyresult = jsonutil.bytetoobject (proxy.request (null, public_key_result_type), keyresult.class); // step2 สร้างสตริงแบบสุ่มและส่งไปยัง WebSerivce String echosttr = strutil.getechostrbyLength (10); Byte [] echobyteparam = rsacoder.encryptBypublickey (echostr.getBytes (), keyresult.getKey ()); Proxy.Request (encoder.encode (echobyteparam), echostr_result_type); // ขั้นตอนที่ 3 เข้ารหัสข้อมูลคำขอไคลเอนต์และส่งไปยัง WebService // ครั้งแรกเข้ารหัสเป็นอาร์เรย์ไบต์จากนั้นแปลงเป็นไบต์สตริง [] ผลลัพธ์ = proxy.request (encoder.encode (cryptutil.encrypt (ค่าคงที่ client_type.getBytes () Keyresult = jsonutil.bytetoobject (ผลลัพธ์, keyresult.class); // step4 ส่งคืนข้อความผ่านการตอบสนองของสตริงเซิร์ฟเวอร์การถอดรหัสรหัสผ่าน = สตริงใหม่ (cryptutil.decrypt (keyresult.getResult (), echostr.getBytes ())); if (response.equals ("1")) {result = true; } หยุดพัก; } catch (exception e) {logger.debug ("th" + i + "การโหลดเวลาเว็บเซิร์ฟเวอร์ล้มเหลว"); i ++; logger.error (e.getMessage (), e); if (i> = 10) {break; }}} ส่งคืนผลลัพธ์;}คำอธิบายสั้น ๆ :
ลูปส่วนใหญ่จะป้องกันไม่ให้บริการส่งคำขออย่างต่อเนื่องเมื่อเครือข่ายถูกตัดการเชื่อมต่อและมากถึง 10 เท่าก็เพียงพอแล้ว
มีสี่ขั้นตอนหลักและสิ่งที่ฉันต้องการอธิบายในความคิดเห็นก็โอเค
③การเข้ารหัสและการถอดรหัสของชั้นเรียนสาธารณะที่ใช้ร่วมกัน
Cryptutil.java
แพ็คเกจ com.honzh.socket.util; นำเข้า Javax.crypto.cipher; นำเข้า Javax.crypto.secretkey; นำเข้า Javax.crypto.secretkeyFactory; นำเข้า Javax.crypto.spec.deskeyspec; @title: เข้ารหัส * @description: Encrypt * @param data * @param key * @return * @throws Exception */ public Static byte [] เข้ารหัส (byte [] data, byte [] คีย์) โยนข้อยกเว้น {key = get8 (คีย์); CIPHER CIPHER = CIPHER.GETINSTANCE ("DES/CBC/PKCS5PADDING"); Deskeyspec Deskeyspec = ใหม่ Deskeyspec (คีย์); SecretKey KeyFactory = SecretKeyFactory.GetInstance ("DES"); SecretKey SecretKey = KeyFactory.GenerAtesecret (Deskeyspec); ivParameterspec IV = ใหม่ ivparameterspec (คีย์); cipher.init (cipher.encrypt_mode, SecretKey, iv); ส่งคืน cipher.dofinal (ข้อมูล); } / ** * @title: decrypt * @description: decrypt * @param data * @param key * @return * @throws Exception * / public Static byte [] decrypt (byte [] data, byte [] คีย์) โยนข้อยกเว้น {key = get8 (key); CIPHER CIPHER = CIPHER.GETINSTANCE ("DES/CBC/PKCS5PADDING"); Deskeyspec Deskeyspec = ใหม่ Deskeyspec (คีย์); secretKeyFactory keyFactory = secretKeyFactory.getInstance ("des"); SecretKey SecretKey = KeyFactory.GenerAtesecret (Deskeyspec); ivParameterspec IV = ใหม่ ivparameterspec (คีย์); cipher.init (cipher.decrypt_mode, Secretkey, iv); ส่งคืน cipher.dofinal (ข้อมูล); } ไบต์คงที่ส่วนตัว [] get8 (ไบต์ [] คีย์) {byte [] key1 = ไบต์ใหม่ [8]; สำหรับ (int i = 0; i <8; i ++) {key1 [i] = key [i]; } return key1; } สตริงคงที่สาธารณะ tohexstring (byte [] data) {string s = ""; สำหรับ (int i = 0; i <data.length; i ++) {s+= integer.tohexstring (data [i] & 0xff)+"-"; } return s; - โดยทั่วไปแล้วการเข้ารหัส SHA และ MD5 นั้นเพียงพอสำหรับเราที่จะใช้!
สำหรับหมวดหมู่เสริมอื่น ๆ ฉันจะไม่แนะนำพวกเขามากนัก มีแหล่งข้อมูลมากมายบนอินเทอร์เน็ตและฉันหวังว่าทุกคนจะได้เรียนรู้ร่วมกัน