ฉันรู้สึกว่ามันเป็นเวลานานแล้วตั้งแต่ฉันเขียนบล็อกครั้งสุดท้าย ให้ฉันบ่นก่อน เดือนนี้ บริษัท ได้ทำงานล่วงเวลาเผยแพร่และเปิดตัวสิ่งพิมพ์และโครงการใหม่แน่นเกินไปดังนั้นฉันจะไม่พูดเกี่ยวกับโครงการที่เฉพาะเจาะจงมากนัก วันนี้มันเป็นสิ่งสำคัญมากที่จะพูดคุยเกี่ยวกับการเข้ารหัสแบบไม่สมมาตร การเข้ารหัสแบบไม่สมมาตรเป็นสิ่งที่ขาดไม่ได้ในชีวิตประจำวันของเรา
แนวคิด
ก่อนที่จะพูดถึง RSA ก่อนอื่นมาพูดถึงการเข้ารหัสแบบไม่สมมาตร เมื่อพูดถึงการเข้ารหัสแบบสมมาตรครั้งหนึ่งเคยกล่าวไว้ว่าอัลกอริทึมการเข้ารหัสแบบสมมาตรใช้คีย์ลับเดียวกันเมื่อเข้ารหัสและถอดรหัสและทั้งสองฝ่ายเพื่อเข้ารหัสและถอดรหัสต้องใช้คีย์เดียวกันเพื่อสื่อสารตามปกติ การเข้ารหัสแบบไม่สมมาตรไม่ใช่กรณี อัลกอริทึมการเข้ารหัสแบบไม่สมมาตรต้องการสองปุ่มในการเข้ารหัสและถอดรหัสคือคีย์สาธารณะและคีย์ส่วนตัว
สิ่งหนึ่งที่ควรทราบคือคีย์สาธารณะและคีย์ส่วนตัวจะต้องเป็นคู่ หากข้อมูลถูกเข้ารหัสด้วยคีย์สาธารณะคุณสามารถถอดรหัสคีย์ส่วนตัวที่สอดคล้องกันได้เท่านั้นและในทางกลับกัน เนื่องจากการเข้ารหัสและการถอดรหัสใช้สองปุ่มที่แตกต่างกันอัลกอริทึมนี้เรียกว่าอัลกอริทึมการเข้ารหัสแบบไม่สมมาตร
กระบวนการทำงาน
ดังที่แสดงในรูปด้านล่างข้อมูลจะถูกส่งโดยใช้การเข้ารหัสแบบไม่สมมาตร
อัลกอริทึมหลักที่ใช้ในการเข้ารหัสแบบไม่สมมาตรรวมถึง: RSA, Elgamal, อัลกอริทึมกระเป๋าเป้สะพายหลัง, Rabin, DH, ECC (อัลกอริทึมการเข้ารหัสเส้นโค้งรูปไข่) ฯลฯ วันนี้เราจะแนะนำ RSA เป็นหลัก สำหรับอัลกอริทึมอื่น ๆ เราจะเลือกไม่กี่คนเพื่อแนะนำพวกเขาในภายหลัง
RSA
ในความเป็นจริง RSA ปรากฏตัวเร็วที่สุดเท่าที่ปี 1978 และเป็นอัลกอริทึมแรกที่สามารถใช้สำหรับการเข้ารหัสข้อมูลและลายเซ็นดิจิตอล เป็นเรื่องง่ายที่จะเข้าใจและใช้งานได้และยังเป็นที่นิยมมาก หลักการเป็นไปตามที่อธิบายไว้ในกระบวนการทำงานข้างต้น
อัลกอริทึม RSA นั้นขึ้นอยู่กับความจริงของทฤษฎีจำนวนง่ายมาก: เป็นเรื่องง่ายที่จะคูณตัวเลขขนาดใหญ่สองตัว แต่มันยากมากที่จะแยกปัจจัยผลิตภัณฑ์ของพวกเขาดังนั้นผลิตภัณฑ์จึงสามารถเปิดเผยได้ว่าเป็นคีย์การเข้ารหัส
การใช้รหัส
มาดูการใช้งานรหัสเฉพาะด้านล่าง
นำเข้า com.google.common.collect.maps; นำเข้า Sun.misc.base64decoder; นำเข้า Sun.misc.base64encoder; นำเข้า Javax.crypto.cipher; นำเข้า Java.Security.*; นำเข้า java.security.interfaces.rsaprivatekey; นำเข้า java.security.interfaces.rsapublickey; นำเข้า java.security.spec.pkcs8encodedkeyspec; นำเข้า java.security.spec.x509encodedkeyspec; นำเข้า java.util.map; /*** สร้างโดย Xiang.li เมื่อปี 2015/3/3 * คลาสเครื่องมือการเข้ารหัสและถอดรหัส RSA*/ คลาสสาธารณะ RSA {/ *** กำหนดวิธีการเข้ารหัส*/ ส่วนตัวสตริงคงสุดท้ายสุดท้ายคีย์ _RSA = "RSA"; / *** กำหนดอัลกอริธึมลายเซ็น*/ สตริงคงสุดท้ายของส่วนตัวคีย์ _rsa_signature = "md5withrsa"; / *** กำหนดอัลกอริทึมคีย์สาธารณะ*/ สตริงคงสุดท้ายของส่วนตัวคีย์ _rsa_publickey = "rsapublickey"; / *** กำหนดอัลกอริทึมคีย์ส่วนตัว*/ สตริงสตริงคงสุดท้ายส่วนตัว key_rsa_privatekey = "rsaprivatekey"; / *** คีย์การเริ่มต้น* @return*/ แผนที่คงที่สาธารณะ <สตริง, วัตถุ> init () {แผนที่ <สตริง, วัตถุ> แผนที่ = null; ลอง {keypairGenerator generator = keypairGenerator.getInstance (key_rsa); generator.initialize (1024); KEYPAIR KEYPAIR = GENERATOR.GenerateKeyPair (); // คีย์สาธารณะ RSAPUBLICKEY PublicKey = (RSAPUBLICKEY) KEYPAIR.GETPOBLIC (); // คีย์ส่วนตัว rsaprivateKey PrivateKey = (rsaprivateKey) Keypair.getPrivate (); // ห่อหุ้มปุ่มเป็นแผนที่ = maps.newhashmap (); map.put (key_rsa_publickey, publickey); map.put (key_rsa_privatekey, privateKey); } catch (nosuchalgorithmexception e) {e.printstacktrace (); } กลับแผนที่; } / *** ใช้คีย์ส่วนตัวเพื่อสร้างลายเซ็นดิจิตอลสำหรับข้อมูล* @param ข้อมูลที่เข้ารหัสข้อมูล* @param privatekey คีย์ส่วนตัว* @return* / เครื่องหมายสตริงคงที่สาธารณะ (BYTE [] ข้อมูล, สตริงส่วนตัว) {string str = ""; ลอง {// decrypt คีย์ส่วนตัวที่เข้ารหัสไบต์ [] bytes = decryptBase64 (PrivateKey); // สร้างวัตถุ PKCS8ENCODEDKEYSPEC PKCS8ENCODEDKEYSPEC PKCS = ใหม่ PKCS8ENCODEDKEYSPEC (ไบต์); // อัลกอริทึมการเข้ารหัสที่ระบุ KeyFactory Factory = keyFactory.getInstance (key_rsa); // รับคีย์ส่วนตัวคีย์คีย์ PrivateKey = Factory.GeneratePrivate (PKCs); // ใช้คีย์ส่วนตัวเพื่อสร้างลายเซ็นดิจิตอลสำหรับลายเซ็นข้อมูล = signature.getInstance (key_rsa_signature); signature.initsign (คีย์); signature.update (ข้อมูล); str = encryptbase64 (signature.sign ()); } catch (exception e) {e.printstacktrace (); } return str; } / *** ตรวจสอบลายเซ็นดิจิตอล* @param data ข้อมูลเข้ารหัส* @param publickey คีย์สาธารณะ* @param Sign Signature Digital* @@Return ตรวจสอบการกลับมาที่ประสบความสำเร็จจริงกลับมาจริง, ส่งคืน FALSE* / BOOLEAN แบบคงที่สาธารณะยืนยัน (BYTE [] ข้อมูล, String PublicKey, String Sign) ลอง {// decrypt คีย์สาธารณะที่เข้ารหัสไบต์ [] bytes = decryptBase64 (PublicKey); // สร้างวัตถุ X509ENCODEDKEYSPEC X509ENCODEDKEYSPEC KEYSPEC = ใหม่ X509ENCODEDKEYSPEC (ไบต์); // อัลกอริทึมการเข้ารหัสที่ระบุ KeyFactory Factory = keyFactory.getInstance (key_rsa); // รับคีย์สาธารณะวัตถุ PublicKey Key = Factory.GeneratePublic (KeySPEC); // ตรวจสอบลายเซ็นดิจิตอลด้วยลายเซ็นรหัสสาธารณะ = Signature.getInstance (key_rsa_signature); signature.initverify (คีย์); signature.update (ข้อมูล); Flag = Signature.Verify (DECRYPTBASE64 (SIGN)); } catch (exception e) {e.printstacktrace (); } return flag; } / *** Decrypt คีย์ส่วนตัว* @param data ข้อมูลเข้ารหัส* @param คีย์คีย์ส่วนตัว* @return* / ไบต์สาธารณะคงที่ [] decryptbyprivatekey (byte [] ข้อมูล, คีย์สตริง) {byte [] result = null; ลอง {// decrypt byte คีย์ส่วนตัว [] bytes = decryptBase64 (คีย์); // รับคีย์ส่วนตัว PKCS8ENCODEDKEYSPEC KEYSPEC = ใหม่ PKCS8ENCODEDKEYSPEC (ไบต์); KeyFactory Factory = keyFactory.getInstance (key_rsa); PrivateKey Privateing = Factory.GeneratePrivate (KeySPEC); // decrypt data cipher cipher = cipher.getInstance (Factory.getAlgorithm ()); cipher.init (cipher.decrypt_mode, PrivateKey); ผลลัพธ์ = cipher.dofinal (ข้อมูล); } catch (exception e) {e.printstacktrace (); } ผลตอบแทนผลลัพธ์; } / *** การถอดรหัสคีย์ส่วนตัว* @param ข้อมูลเข้ารหัสข้อมูล* @param คีย์คีย์สาธารณะ* @return* / ไบต์คงที่สาธารณะ [] DecryptByPublicKey (BYTE [] ข้อมูล, สตริงคีย์) {byte [] result = null; ลอง {// decrypt ไบต์คีย์สาธารณะ [] bytes = decryptBase64 (คีย์); // รับคีย์สาธารณะ X509ENCODEDKEYSPEC KEYSPEC = ใหม่ X509ENCODEDKEYSPEC (ไบต์); KeyFactory Factory = keyFactory.getInstance (key_rsa); PublicKey = Factory.GeneratePublic (KeySPEC); // decrypt data cipher cipher = cipher.getInstance (Factory.getAlgorithm ()); cipher.init (cipher.decrypt_mode, PublicKey); ผลลัพธ์ = cipher.dofinal (ข้อมูล); } catch (exception e) {e.printstacktrace (); } ผลตอบแทนผลลัพธ์; } / *** การเข้ารหัสคีย์สาธารณะ* @param data data ที่จะเข้ารหัส* @param คีย์คีย์สาธารณะ* @return* / ไบต์คงที่สาธารณะ [] EncryptByPublicKey (ไบต์ [] ข้อมูลคีย์สตริง) {byte [] result = null; ลอง {byte [] bytes = decryptBase64 (คีย์); // รับคีย์สาธารณะ X509ENCODEDKEYSPEC KEYSPEC = ใหม่ X509ENCODEDKEYSPEC (ไบต์); KeyFactory Factory = keyFactory.getInstance (key_rsa); PublicKey = Factory.GeneratePublic (KeySPEC); // Encrypt Data Cipher Cipher = cipher.getInstance (Factory.getAlgorithm ()); cipher.init (cipher.encrypt_mode, PublicKey); ผลลัพธ์ = cipher.dofinal (ข้อมูล); } catch (exception e) {e.printstacktrace (); } ผลตอบแทนผลลัพธ์; } / *** การเข้ารหัสคีย์ส่วนตัว* @param data ที่จะเข้ารหัส* @param คีย์คีย์ส่วนตัว* @return* / ไบต์คงที่สาธารณะ [] EncryptbyPrivateKey (ไบต์ [] ข้อมูลคีย์สตริง) {byte [] ผลลัพธ์ = null; ลอง {byte [] bytes = decryptBase64 (คีย์); // รับคีย์ส่วนตัว PKCS8ENCODEDKEYSPEC KEYSPEC = ใหม่ PKCS8ENCODEDKEYSPEC (ไบต์); KeyFactory Factory = keyFactory.getInstance (key_rsa); PrivateKey Privateing = Factory.GeneratePrivate (KeySPEC); // Encrypt Data Cipher Cipher = cipher.getInstance (Factory.getAlgorithm ()); cipher.init (cipher.encrypt_mode, PrivateKey); ผลลัพธ์ = cipher.dofinal (ข้อมูล); } catch (exception e) {e.printstacktrace (); } ผลตอบแทนผลลัพธ์; } / ** * รับคีย์สาธารณะ * @param map * @return * / สตริงคงที่สาธารณะ getPublickey (แผนที่ <สตริงวัตถุ> แผนที่) {string str = ""; ลอง {key key = (key) map.get (key_rsa_publickey); str = encryptbase64 (key.getEncoded ()); } catch (exception e) {e.printstacktrace (); } return str; } / ** * รับคีย์ส่วนตัว * @param map * @return * / สตริงคงที่สาธารณะ getPrivateKey (แผนที่ <สตริงวัตถุ> แผนที่) {String str = ""; ลอง {key key = (key) map.get (key_rsa_privatekey); str = encryptbase64 (key.getEncoded ()); } catch (exception e) {e.printstacktrace (); } return str; } / *** base64 decrypt* @param คีย์สตริงที่ต้องถอดรหัส* @return byte array* @throws exception* / public static byte [] decryptBase64 (คีย์สตริง) โยนข้อยกเว้น {return (ใหม่ base64Decoder ()) } / *** การเข้ารหัส base64* @param คีย์อาร์เรย์ไบต์ที่ต้องเข้ารหัส* @return String* @throws Exception* / String String สาธารณะ EncryptBase64 (BYTE [] คีย์) โยนข้อยกเว้น {return (ใหม่ BASE64ENCODER ()) } / *** วิธีการทดสอบ* @param args* / โมฆะคงที่สาธารณะหลัก (สตริง [] args) {String privateKey = ""; String PublicKey = ""; // สร้างแผนที่คีย์ส่วนตัวคีย์ <String, Object> MAP = Init (); PublicKey = getPublicKey (แผนที่); PrivateKey = getPrivateKey (แผนที่); System.out.println ("คีย์สาธารณะ: /n /r" + PublicKey); System.out.println ("คีย์ส่วนตัว: /n /r" + PrivateKey); System.out.println ("การเข้ารหัสคีย์สาธารณะ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- EncryptBypublicKey (Word.getBytes (), PublicKey); การเข้ารหัส ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ENCRYPTBYPRIVATEKEY (English.getBytes (), PrivateKey); String decenglish = สตริงใหม่ (DECRYPTBYBUBLICKEY (Encenglish, PublicKey)); System.out.println ("ก่อนการเข้ารหัส:" + ภาษาอังกฤษ + "/n/r" + "หลังจากถอดรหัส:" + Decenglish); System.out.println ("ลายเซ็นการตรวจสอบคีย์-คีย์ส่วนตัว-ลายเซ็นการตรวจสอบคีย์"); // สร้างเครื่องหมายสตริงลายเซ็น = Sign (Encenglish, PrivateKey); System.out.println ("ลายเซ็น:/r" + เครื่องหมาย); // ตรวจสอบสถานะบูลีนลายเซ็น = ตรวจสอบ (Encenglish, PublicKey, Sign); System.out.println ("สถานะ:/r" + สถานะ); - เข้ารหัสและถอดรหัสผลลัพธ์
บทสรุป
ในความเป็นจริงกระบวนการที่ซับซ้อนดูเหมือนจะสามารถอธิบายได้ในประโยคเดียว: การใช้การเข้ารหัสคีย์สาธารณะและการถอดรหัสคีย์ส่วนตัวการถ่ายโอนข้อมูลหนึ่งครั้งจากปาร์ตี้ B ไปยังปาร์ตี้ A เสร็จสมบูรณ์ผ่านการเข้ารหัสคีย์ส่วนตัวและการถอดรหัสคีย์สาธารณะและในเวลาเดียวกัน
การเกิดขึ้นของอัลกอริทึมการเข้ารหัสแบบไม่สมมาตรคือการแก้ปัญหาการเข้ารหัสและถอดรหัสเพียงคีย์เดียวเท่านั้น ตราบใดที่คีย์นี้สูญหายหรือเปิดเผยข้อมูลที่เข้ารหัสจะถูกโจมตีได้อย่างง่ายดาย ในเวลาเดียวกันมันเป็นเพราะการเกิดขึ้นของอัลกอริทึมการเข้ารหัสแบบไม่สมมาตรซึ่งได้รับลายเซ็นดิจิตอลใบรับรองดิจิตอล ฯลฯ
โอเควันนี้หยุดที่นี่ บทความถัดไปยังคงการเข้ารหัสแบบไม่สมมาตร ในเวลานั้นฉันจะรู้ในเวลานั้น เก็บเป็นความลับที่นี่ก่อน