แนวคิดรหัสผ่านแบบไม่สมมาตร
1. ความแตกต่างที่สำคัญจากอัลกอริทึมการเข้ารหัสแบบสมมาตรคือปุ่มเข้ารหัสและการถอดรหัสนั้นแตกต่างกันอย่างใดอย่างหนึ่งคือสาธารณะ (คีย์สาธารณะ) และอีกปุ่มหนึ่งเป็นความลับ (คีย์ส่วนตัว) ส่วนใหญ่จะแก้ปัญหาการจัดการการจัดสรรที่สำคัญของอัลกอริทึมการเข้ารหัสแบบสมมาตรและปรับปรุงความปลอดภัยของอัลกอริทึม
2. ประสิทธิภาพการเข้ารหัสและการถอดรหัสของอัลกอริทึมการเข้ารหัสแบบไม่สมมาตรค่อนข้างต่ำ ในการออกแบบอัลกอริทึมอัลกอริทึมการเข้ารหัสแบบไม่สมมาตรมีข้อกำหนดที่เข้มงวดเกี่ยวกับความยาวของข้อมูลที่เข้ารหัส ตัวอย่างเช่นอัลกอริทึม RSA ต้องการให้ข้อมูลที่จะเข้ารหัสจะต้องไม่เกิน 53 ไบต์
3. อัลกอริทึมการเข้ารหัสแบบไม่สมมาตรส่วนใหญ่จะใช้เพื่อแลกเปลี่ยนคีย์ของอัลกอริทึมการเข้ารหัสแบบสมมาตรมากกว่าการแลกเปลี่ยนข้อมูล
4. Java6 ให้อัลกอริทึมสองอัลกอริทึมที่ใช้ DH และ RSA Bouncy Castle ให้การสนับสนุนอัลกอริทึม E1GAMAL นอกเหนือจากอัลกอริทึมสามตัวข้างต้นแล้วยังมีอัลกอริทึม ECC และปัจจุบันยังไม่มีส่วนประกอบโอเพนซอร์สที่เกี่ยวข้องที่จะให้การสนับสนุน
จำเป็นต้องมีสองปุ่มสำหรับการเข้ารหัสหรือถอดรหัสแบ่งออกเป็นกุญแจสาธารณะและส่วนตัว
คุณสมบัติ: ความปลอดภัยสูงความเร็วช้า
ใช้
【การแลกเปลี่ยนคีย์ (DH) 】
โดยไม่ต้องพิจารณาคีย์ทั่วไปทั้งสองฝ่ายสร้างคีย์และไม่ได้ให้การเข้ารหัส การเข้ารหัสและการถอดรหัสยังต้องใช้อัลกอริทึมการเข้ารหัสแบบสมมาตรอื่น ๆ เพื่อนำไปใช้
ตัวอย่างอัลกอริทึม DH
นำเข้า Javax.crypto.keyagreement; นำเข้า Javax.crypto.interfaces.dhprivatekey นำเข้า Javax.crypto.interfaces.dhpublickey นำเข้า Javax.crypto.spec.dhparameterspec; นำเข้า Java.security java.security.spec.x509encodedkeyspec; นำเข้า java.util.hashmap; นำเข้า java.util.map; // 1 สร้างคีย์แหล่งที่มา // 2 คีย์สาธารณะของแหล่งที่มาถูกส่งไปยังเป้าหมายและเป้าหมายจะสร้างกุญแจสาธารณะและคีย์ส่วนตัวผ่านแหล่งที่มา // 3 คีย์สาธารณะของเป้าหมายถูกส่งไปยังแหล่งที่มา // 4 ทั้งสองฝ่ายใช้คีย์สาธารณะของอีกฝ่ายและคีย์ส่วนตัวของตัวเองเพื่อสร้างคีย์ท้องถิ่น // 5 หากทั้งสองฝ่ายสร้างคีย์ท้องถิ่นเดียวกัน สตริงสุดท้ายคงที่สาธารณะ private_key = "dh_private_key"; /** * สร้างคู่คีย์ต้นฉบับ * @return * @throws Exception */แผนที่คงที่ <String, Object> InitsourceKey () โยนข้อยกเว้น {// สร้างอินสแตนซ์ของ KeypairGenerator เลือก KypairGenerator Keygenerator = KeypairGenerator.getInstance // เริ่มต้นความยาวคีย์, ค่าเริ่มต้น 1024, ช่วงตัวเลือก 512-65536 & ทวีคูณของ 64 keypairgenerator.initialize (1024); // สร้างคีย์คู่ Keypair Keypair = KeypairGenerator.generateKeyPair (); dhpublickey dhpublickey = (dhpublickey) keypair.getpublic (); dhprivatekey dhprivatekey = (dhprivatekey) keypair.getPrivate (); // ใส่คู่คีย์ลงในแผนที่ <string, Object> keymap = new hashmap <string, object> (); keymap.put (public_key, dhpublickey); keymap.put (private_key, dhprivatekey); คืนกุญแจ } / ** * สร้างคู่คีย์เป้าหมายผ่านคีย์สาธารณะแหล่งที่มา * @param SourcePublickey * @return * @throws Exception * / แผนที่สาธารณะคงที่ <สตริงวัตถุ> inittargetKey (Byte [] SourcePublicKey) โยนข้อยกเว้น {keyFactory keyFactory. // ใช้คีย์สาธารณะต้นทางสร้าง KeySPEC และใช้ KeyFactory เพื่อสร้างข้อมูลที่เกี่ยวข้องกับแหล่งข้อมูลสาธารณะ X509ENCODEDKEYSPEC KEYSPEC = ใหม่ X509ENCODEDKEYSPEC (SourcePublicKey); dhpublickey sourcePublic = (dhpublickey) keyfactory.generatepublic (Keyspec); DhParameterspec DHPublicKeyParams = SourcePublic.getParams (); KEYPAIRGENERATOR KEYPAIRGENERATOR = KEYPAIRENERATOR.GETINSTANCE ("DH"); Keypairgenerator.initialize (DHPublicKeyParams); KEYPAIR KEYPAIR = KEYPAIRENERATOR.GenerateKeyPair (); dhpublickey dhpublickey = (dhpublickey) keypair.getpublic (); dhprivatekey dhprivatekey = (dhprivatekey) keypair.getPrivate (); // ใส่คู่คีย์ลงในแผนที่ <string, Object> keymap = new hashmap <string, object> (); keymap.put (public_key, dhpublickey); keymap.put (private_key, dhprivatekey); คืนกุญแจ } / *** ใช้คีย์สาธารณะของฝ่ายหนึ่งและคีย์ส่วนตัวของอีกฝ่ายเพื่อสร้างคีย์ท้องถิ่น* @return* / ไบต์คงที่สาธารณะ [] Generatelocalsecretkey (byte [] apublickey, byte [] bprivatekey) โยนข้อยกเว้น // ใช้คีย์สาธารณะสร้าง keyspec และใช้ keyFactory เพื่อสร้างข้อมูลที่เกี่ยวข้องกับ PublicKey X509ENCODEDKEYSPEC KEYSPEC = ใหม่ X509ENCODEDKEYSPEC (APUBLICKEY); PublicKey = keyFactory.generatePublic (KeySpec); // ใช้ b คีย์ส่วนตัว, สร้างข้อมูลที่เกี่ยวข้องกับ PrivateKey PKCS8ENCODEDKEYSPEC PKCS8ENCODEDKEYSPEC = ใหม่ PKCS8ENCODEDKEYSPEC (BPRIVATEKEY); PrivateKey Privateing = keyFactory.generatePrivate (PKCS8ENCODEDKEYSPEC); // เข้ารหัส PublicKey ของ A และ PrivateKey ของ B ผ่าน keyagreement keyagreement = keyagreement.getInstance ("DH"); keyagreement.init (PrivateKey); keyagreement.dophase (PublicKey, True); ส่งคืน keyagreement.generatesecret ("AES"). getEncoded (); // อัลกอริทึมใช้อัลกอริทึมการเข้ารหัสแบบสมมาตร (DES, DESEDE, AES) // ส่งคืน keyAgreement.generAtesecret (); // อัลกอริทึมยังสามารถใช้ในการคำนวณโดยใช้วิธีเริ่มต้นโดยไม่ต้องเลือกอัลกอริทึม} // รับคีย์สาธารณะอาร์เรย์ไบต์สาธารณะคงที่ [] getPublickey (แผนที่ <สตริงวัตถุ> แผนที่) {return ((dhpublickey) map.get (public_key) } // รับคีย์ส่วนตัวไบต์อาร์เรย์สาธารณะคงที่ไบต์ [] getPrivateKey (แผนที่ <สตริงวัตถุ> แผนที่) {return ((dhprivatekey) map.get (ส่วนตัว)). getenCoded (); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่นข้อยกเว้น {byte [] source_public_key; ไบต์ [] source_private_key; ไบต์ [] source_local_key; BYTE [] target_public_key; BYTE [] target_private_key; ไบต์ [] target_local_key; แผนที่ <string, Object> sourceKey = initSourceKey (); source_public_key = getPublickey (sourceKey); source_private_key = getPrivateKey (SourceKey); System.out.println ("คีย์สาธารณะที่มา:"+bytestohex.frombytestohex (source_public_key)); System.out.println ("แหล่งที่มาส่วนตัว:"+bytestohex.frombytestohex (source_private_key)); แผนที่ <string, Object> TargetKey = InittArgetKey (getPublicKey (SourceKey)); target_public_key = getPublickey (TargetKey); target_private_key = getPrivateKey (TargetKey); System.out.println ("คีย์สาธารณะเป้าหมาย:"+bytestohex.frombytestohex (target_public_key)); System.out.println ("Target Private Key:"+bytestohex.frombytestohex (target_private_key)); source_local_key = generatelocalsecretkey (target_public_key, source_private_key); target_local_key = generatelocalsecretkey (source_public_key, target_private_key); System.out.println ("แหล่งที่มาโลคัลคีย์:"+bytestohex.frombytestohex (source_local_key)); System.out.println ("คีย์โลคัลเป้าหมาย:"+bytestohex.frombytestohex (target_local_key)); -【การเข้ารหัส/ถอดรหัส (RSA) 】【ลายเซ็นดิจิตอล (RSA) 】
อัลกอริทึม RSA นั้นช้ากว่าอัลกอริทึม DH และตัวอักษรทั้งห้าทั้งหมดนี้เป็นตัวอักษรตัวแรกของชื่อมนุษย์ อัลกอริทึม DH เป็นระบบการเข้ารหัสลับแบบอสมมาตรแรก
อัลกอริทึม RSA มีความเร็วในการคำนวณที่ช้าและไม่เหมาะสำหรับการเข้ารหัสข้อมูลจำนวนมาก ทางออกหนึ่งคือการผสมวิธีการเข้ารหัส RSA และสมมาตร, เข้ารหัสข้อมูลโดยใช้วิธีการเข้ารหัสแบบสมมาตรและปุ่มเข้ารหัสแบบสมมาตรจะถูกเข้ารหัสโดยใช้อัลกอริทึม RSA เพราะกุญแจสั้นมากเวลาไม่มากเกินไป ในความเป็นจริงข้อเสียเพียงอย่างเดียวของวิธีการเข้ารหัสแบบสมมาตรคือคีย์นั้นยากที่จะผ่านและวิธีการเข้ารหัสแบบสมมาตรก็ยากที่จะแตก
สถานการณ์ที่เกี่ยวข้องของ RSA:
(1) เซิร์ฟเวอร์สร้างคีย์สาธารณะและคีย์ส่วนตัวและเผยแพร่คีย์สาธารณะ
(2) ไคลเอนต์ใช้คีย์สาธารณะเพื่อเข้ารหัสข้อมูลและส่งมอบให้กับเซิร์ฟเวอร์ คนอื่นไม่สามารถเข้าใจข้อมูลที่เข้ารหัสได้
(3) เซิร์ฟเวอร์ใช้คีย์ส่วนตัวเพื่อถอดรหัสข้อมูลและดูข้อมูลที่ส่งโดยผู้ใช้
ในกรณีนี้คีย์สาธารณะเป็นเหมือนกล่องจดหมายและทุกคนสามารถใส่ข้อความลงในกล่องจดหมายนี้ได้ แต่เฉพาะผู้ที่มีคีย์กล่องจดหมายเท่านั้นที่สามารถยกเลิกกล่องและดูจดหมายในกล่องจดหมายนี้
RSA สถานการณ์ที่ใช้งานได้ 2:
(1) จักรพรรดิสร้างคีย์สาธารณะและคีย์ลับและเผยแพร่คีย์สาธารณะ
(2) จักรพรรดิออกคำสั่งเพื่อแจ้งให้โลกทราบ มีตัวเลขสองสตริงที่มุมล่างขวาของคำสั่ง สตริงแรกเป็นสตริงสุ่มและสตริงที่สองเป็นผลลัพธ์ของการเข้ารหัสสตริงแรกด้วยคีย์ส่วนตัว
(3) บางคนไม่เชื่อว่าคำสั่งถูกเขียนขึ้นโดยจักรพรรดิดังนั้นพวกเขาจึงถอดรหัสหมายเลขสตริงที่สองโดยใช้คีย์สาธารณะ หลังจากถอดรหัสพวกเขาพบว่ามันเหมือนกับสตริงแรกของตัวเลขซึ่งหมายความว่ามันถูกเขียนโดยจักรพรรดิ เนื่องจากคนส่วนใหญ่ไม่มีคีย์พวกเขาจึงไม่สามารถเข้ารหัสข้อมูลที่สามารถถอดรหัสด้วยคีย์สาธารณะได้
ในกรณีนี้คีย์สาธารณะใช้สำหรับการถอดรหัสและใช้คีย์ส่วนตัวสำหรับการเข้ารหัส สิ่งนี้สามารถใช้เพื่อพิสูจน์ว่าการประกาศถูกส่งโดยใครบางคน มันเทียบเท่ากับลายเซ็น
ในความเป็นจริงไม่จำเป็นต้องมีความยาวเป็นพิเศษสำหรับลายเซ็น โดยทั่วไปแล้วลายเซ็นมีความยาวคงที่ หากคุณต้องการมีความยาวคงที่คุณสามารถใช้อัลกอริทึม MessageDigest เช่น MD5 และ SHA Series ดังนั้นจึงมีอัลกอริทึมลายเซ็นหลากหลายเช่น MD5 WithRSA ฯลฯ
ตัวอย่างการเข้ารหัส/ถอดรหัส RSA
นำเข้า Javax.crypto.cipher; นำเข้า java.security.keypair; นำเข้า Java.security.keypairgenerator; นำเข้า Java.security.publickey; นำเข้า Java.security.interfaces.rsaprivatekey; java.util.map;/*** เครื่องมือเข้ารหัส RSA*/คลาสสาธารณะ rsautil {สตริงสุดท้ายคงที่สาธารณะ public_key = "rsa_public_key"; สตริงสุดท้ายคงที่สาธารณะ private_key = "rsa_private_key"; / ** * คีย์การเริ่มต้น * @return * @Throws Exception */ แผนที่คงที่สาธารณะ <String, Object> InitKey () พ่นข้อยกเว้น {KeypairGenerator KeypairGenerator = KeypairGenerator.getInstance ("RSA"); KEYPAIRGENERATOR.Initialize (1024); // 512-65536 & ทวีคูณของ 64 Keypair Keypair = KeypairGenerator.GenerateKeyPair (); RSAPUBLICKEY PublicKey = (RSAPUBLICKEY) KEYPAIR.GETPOBLIC (); rsaprivatekey privateKey = (rsaprivatekey) keypair.getPrivate (); แผนที่ <string, Object> keymap = new hashmap <string, object> (); keymap.put (public_key, publickey); keymap.put (private_key, privateKey); คืนกุญแจ } สาธารณะคงที่ rsapublickey getPublickey (แผนที่ <สตริงวัตถุ> keymap) {return (rsapublickey) keymap.get (public_key); } สาธารณะคงที่ rsaprivatekey getPrivateKey (แผนที่ <สตริงวัตถุ> keymap) {return (rsaprivatekey) keymap.get (private_key); } / ** * เข้ารหัสข้อมูลโดยใช้คีย์สาธารณะ * @param data * @param PublicKey * @return * @throws Exception * / public Static byte [] Encrypt (byte [] data, rsapublickey publickey) โยนข้อยกเว้น {cipher cipher = cipher.getinstance cipher.init (cipher.encrypt_mode, PublicKey); ส่งคืน cipher.dofinal (ข้อมูล); } / ** * ใช้คีย์ส่วนตัวเพื่อถอดรหัส * @param data * @param PrivateKey * @return * @throws Exception * / public Static byte [] decrypt (byte [] data, rsaprivatekey Key) โยนข้อยกเว้น {cipher cipher = cipher.getinstance cipher.init (cipher.decrypt_mode, PrivateKey); ส่งคืน cipher.dofinal (ข้อมูล); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น {สตริง data = "jay chou-dongfeng break"; แผนที่ <สตริงวัตถุ> keymap = initKey (); ไบต์ [] miwen = encrypt (data.getBytes (), getPublicKey (keymap)); System.out.println ("เนื้อหาที่เข้ารหัส:"+bytestohex.frombytestohex (Miwen)); ไบต์ [] plain = decrypt (Miwen, getPrivateKey (keymap)); System.out.println ("เนื้อหาที่ถอดรหัส:"+สตริงใหม่ (ธรรมดา)); -ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น