อัลกอริทึมการเข้ารหัส RSA
ลองทบทวนอัลกอริทึมการเข้ารหัสของ RSA เราใช้ภาษาที่ค่อนข้างมาตรฐานเพื่ออธิบายอัลกอริทึมนี้ตามคำจำกัดความของอัลกอริทึมการเข้ารหัสคีย์สาธารณะและอัลกอริทึมลายเซ็น
ระบบเข้ารหัสคีย์สาธารณะ RSA รวมถึงอัลกอริทึม 3 ตัวต่อไปนี้: Keygen (อัลกอริทึมการสร้างคีย์), เข้ารหัส (เข้ารหัส) และ DECRYPT (อัลกอริทึมการถอดรหัส)
อัลกอริทึมการสร้างคีย์ใช้ค่าคงที่ความปลอดภัยเป็นอินพุตเพื่อส่งออก PK คีย์สาธารณะและ SK คีย์ส่วนตัว ค่าคงที่ความปลอดภัยถูกใช้เพื่อกำหนดความปลอดภัยของอัลกอริทึมการเข้ารหัสซึ่งโดยทั่วไปเกี่ยวข้องกับขนาดของจำนวน Prime P ที่ใช้โดยอัลกอริทึมการเข้ารหัส ยิ่งจำนวน Prime P คือยิ่งระบบมีขนาดใหญ่ขึ้น ใน RSA อัลกอริทึมการสร้างคีย์มีดังนี้: อัลกอริทึมแรกจะสร้างตัวเลขสำคัญขนาดใหญ่ที่แตกต่างกันสองครั้ง P และ Q และคำนวณ N = PQ จากนั้นอัลกอริทึมจะคำนวณฟังก์ชั่นออยเลอร์ ถัดไปอัลกอริทึมแบบสุ่มเลือกจำนวนเต็มน้อยกว่า E และคำนวณองค์ประกอบของโมดูโลผกผัน D ของ E ในที่สุดคีย์สาธารณะคือ pk = (n, e) และคีย์ส่วนตัวคือ sk = (n, d)
อัลกอริทึมการเข้ารหัสใช้คีย์สาธารณะ PK และข้อความ M ที่จะเข้ารหัสเป็นอินพุตและส่งออก ciphertext CT ใน RSA อัลกอริทึมการเข้ารหัสมีดังนี้: อัลกอริทึมส่งออก ciphertext โดยตรงเป็นอัลกอริทึมการถอดรหัสใช้คีย์ส่วนตัว SK และ CIPHERTEXT CT เป็นอินพุตและส่งข้อความ M. ใน RSA เนื่องจาก E และ D อยู่ตรงข้ามกันเราจึงมี:
ดังนั้นจากคำอธิบายอัลกอริทึมเรายังสามารถเห็นได้ว่าคีย์สาธารณะใช้เพื่อเข้ารหัสข้อมูลและคีย์ส่วนตัวใช้เพื่อถอดรหัสข้อมูล แน่นอนว่าสิ่งนี้สามารถเข้าใจได้อย่างสังหรณ์ใจ: คีย์สาธารณะเป็นคีย์สาธารณะและเมื่อมีการเปิดเผยทุกคนสามารถใช้มันเพื่อเข้ารหัสข้อมูล คีย์ส่วนตัวคือคีย์ส่วนตัวและใครก็ตามที่มีคีย์นี้สามารถถอดรหัส ciphertext ได้ มิฉะนั้นหากทุกคนสามารถเห็นคีย์ส่วนตัวและถอดรหัสได้มันจะเป็นระเบียบ
มาดูการใช้งานง่าย ๆ ใน Java:
แพ็คเกจ com.stone.security; นำเข้า Java.security.keypair; นำเข้า java.security.keypairgenerator; นำเข้า Java.Security.PrivateKey; นำเข้า java.security.publickey; นำเข้า Java.util.Arrays; นำเข้า Javax.crypto.cipher; / *** อัลกอริทึม RSA การเข้ารหัสการเข้ารหัสแบบอสมมาตรแบบอสมมาตร*/ คลาสสาธารณะ RSA {สตริงสุดท้ายคงที่คีย์ _Algorithm = "RSA"; สาธารณะคงที่สตริงสุดท้าย cipher_algorithm_ecb1 = "rsa/ecb/pkcs1padding"; สาธารณะคงที่สตริงสุดท้าย cipher_algorithm_ecb2 = "rsa/ecb/oaepwithsha-1andmgf1padding"; // คุณไม่สามารถใช้สตริงสุดท้ายคงที่ cipher_algorithm_ecb3 = "oaepwithsha-256andmgf1padding"; // คุณไม่สามารถใช้ PublicKey แบบคงที่ Static Private Key Key; ตัวเลขตัวเลขคงที่; แป้นพิมพ์คีย์ปาร์แบบคงที่; โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น {method1 ("skoda u*(sfsad7f ()*^%% $"); method2 ("skoda u*(sfsad7f ()*^%% $"); method3 ("skoda u*(sfsad7f () cipher_algorithm_ecb1 * @param str * @throws exception */ โมฆะคงที่วิธีการ 1 (String str) โยนข้อยกเว้น {keygenerator keygenerator = keypairgenerator.getInstance (key_algorithm); Keypair.getPrivate (); arrays.toString (เข้ารหัส); cipher_algorithm_ecb1 * @param str * @throws exception */ โมฆะคงที่ method2 (string str) โยนข้อยกเว้น {keygenerator keygenerator = keypairgenerator.getInstance (key_algorithm); KEYPAIR KEYPAIR = KEYGENERATOR.GenerateKeyPair (); PublicKey = Keypair.getPublic (); PrivateKey = Keypair.getPrivate (); cipher = cipher.getInstance (key_algorithm); cipher.init (cipher.encrypt_mode, PrivateKey); // คีย์ส่วนตัวการเข้ารหัสไบต์ [] encrypt = cipher.dofinal (str.getBytes ()); System.out.println ("การเข้ารหัสคีย์ส่วนตัว 2:" + array.toString (เข้ารหัส)); cipher.init (cipher.decrypt_mode, PublicKey); // คีย์สาธารณะ decrypt byte [] decrypt = cipher.dofinal (เข้ารหัส); System.out.println ("Decrypt คีย์สาธารณะ 2:" + สตริงใหม่ (DECRYPT)); }/** * การเข้ารหัสคีย์ส่วนตัวการถอดรหัสคีย์สาธารณะใช้ cipher_algorithm_ecb1 = rsa/ecb/pkcs1padding * @param str * @throws exception */โมฆะแบบคงที่ KEYPAIR KEYPAIR = KEYGENERATOR.GenerateKeyPair (); PublicKey = Keypair.getPublic (); PrivateKey = Keypair.getPrivate (); cipher = cipher.getInstance (cipher_algorithm_ecb1); cipher.init (cipher.encrypt_mode, PrivateKey); // คีย์ส่วนตัวการเข้ารหัสไบต์ [] encrypt = cipher.dofinal (str.getBytes ()); System.out.println ("การเข้ารหัสคีย์ส่วนตัว 3:" + array.toString (เข้ารหัส)); cipher.init (cipher.decrypt_mode, PublicKey); // คีย์สาธารณะการถอดรหัสไบต์ [] decrypt = cipher.dofinal (เข้ารหัส); System.out.println ("3 หลังจากการถอดรหัสคีย์สาธารณะ:" + สตริงใหม่ (DECRYPT)); - อัลกอริทึม DSA และลายเซ็นดิจิตอล
โดยทั่วไปแล้ว DSA จะใช้สำหรับลายเซ็นดิจิตอลและการรับรอง
DSA เป็นตัวแปรของอัลกอริทึม SCHNORR และ ELGAMAL Signature และใช้โดย NIST ในสหรัฐอเมริกาเป็น DSS (มาตรฐานลายเซ็นดิจิตอล)
DSA ขึ้นอยู่กับปัญหาลอการิทึมแบบไม่ต่อเนื่องของจำนวนเต็มโดเมนและความปลอดภัยของมันคล้ายกับ RSA
ในลายเซ็นดิจิตอล DSA และการรับรองความถูกต้องผู้ส่งใช้คีย์ส่วนตัวของเขาเองเพื่อลงนามในไฟล์หรือข้อความและผู้รับใช้คีย์สาธารณะของผู้ส่งเพื่อตรวจสอบความถูกต้องของลายเซ็นหลังจากได้รับข้อความ DSA เป็นเพียงอัลกอริทึมและความแตกต่างระหว่าง RSA คือไม่สามารถใช้สำหรับการเข้ารหัสและถอดรหัสหรือสำหรับการแลกเปลี่ยนที่สำคัญ
สำหรับลายเซ็นเท่านั้นมันเร็วกว่า RSA มาก
แพ็คเกจ com.stone.security; นำเข้า java.security.key; นำเข้า Java.security.keyfactory; นำเข้า Java.security.keypair; นำเข้า java.security.keypairgenerator; นำเข้า Java.Security.PrivateKey; นำเข้า java.security.publickey; นำเข้า Java.security.Securerandom; นำเข้า Java.security.Signature; นำเข้า java.security.spec.pkcs8encodedkeyspec; นำเข้า java.security.spec.x509encodedkeyspec; นำเข้า java.util.hashmap; นำเข้า java.util.map; นำเข้า Sun.misc.base64decoder; นำเข้า Sun.misc.base64encoder; /*** อัลกอริทึมลายเซ็น DSA-Digital เป็นตัวแปรของอัลกอริทึม SCHNORR และ ELGAMAL Signature และใช้เป็น DSS โดย NIST ในสหรัฐอเมริกา * ในระยะสั้นนี่เป็นวิธีการตรวจสอบขั้นสูงที่ใช้เป็นลายเซ็นดิจิตอล ไม่เพียง แต่กุญแจสาธารณะและส่วนตัวเท่านั้น แต่ยังรวมถึงลายเซ็นดิจิตอลด้วย การเข้ารหัสคีย์ส่วนตัวสร้างลายเซ็นดิจิตอลข้อมูลการตรวจสอบคีย์สาธารณะและลายเซ็น * หากข้อมูลและลายเซ็นไม่ตรงกันการตรวจสอบจะถูกพิจารณาว่าล้มเหลว! นั่นคือข้อมูลในการส่งสัญญาณไม่สามารถเข้ารหัสได้อีกต่อไป หลังจากที่ผู้รับได้รับข้อมูลเขาได้รับรหัสสาธารณะและลายเซ็นเพื่อตรวจสอบว่าข้อมูลนั้นถูกต้องหรือไม่ */ คลาสสาธารณะ DSA {/ ***ไม่เพียง แต่คุณสามารถใช้อัลกอริทึม DSA เท่านั้น แต่คุณยังสามารถใช้อัลกอริทึม RSA สำหรับลายเซ็นดิจิตอล*/ สตริงสุดท้ายคงที่คีย์ _algorithm = "RSA"; สาธารณะคงที่สตริงสุดท้าย Signature_Algorithm = "MD5WithRSA";*/ สตริงสุดท้ายคงที่สาธารณะ key_Algorithm = "DSA"; สาธารณะคงที่สตริงสุดท้าย Signature_Algorithm = "DSA"; สตริงสุดท้ายคงที่สาธารณะ default_seed = "$%^*%^() (hjg8awfjas7"; // เริ่มต้นเมล็ดพันธุ์สาธารณะคงที่สตริงสุดท้าย public_key = "dsapublickey"; สตริงสุดท้ายคงที่ private_key = "dsaprivatekey" คุณ*() _ + "; byte [] data = str.getBytes (); แผนที่ <string, object> keymap = initKey (); // สร้างคีย์ PublicKey = (publicKey) keymap.get (public_key); privateKey PrivateKey = (ส่วนตัว) System.out.println ("รูปแบบคีย์สาธารณะ:" + publickey.getFormat ()); Verify1); } / *** สร้างคีย์** @param เมล็ดเมล็ด* @return Key Object* @throws Exception* / แผนที่สาธารณะ <String, Object> InitKey (String Seed) โยนข้อยกเว้น {System.out.println ("สร้างคีย์"); Keygenerator keygen = KeypairGenerator.getInstance (key_algorithm); Securerandom Securerandom = ใหม่ securerandom (); Securerandom.setseed (seed.getBytes ()); // ขนาดโมดูลัสต้องอยู่ในช่วง 512 ถึง 1024 และเป็นหลายของ 64 keygen.initialize (640, securerandom); ปุ่ม Keypair = keygen.genkeypair (); PrivateKey Privateing = keys.getPrivate (); PublicKey = keys.getPublic (); แผนที่ <string, Object> map = new hashmap <string, object> (2); map.put (public_key, publickey); map.put (private_key, privateKey); แผนที่กลับ; } / *** สร้างคีย์เริ่มต้น** @return Key Object* @Throws Exception* / Public Static Map <String, Object> InitKey () โยนข้อยกเว้น {return initKey (default_seed); } / ** * รับคีย์ส่วนตัว * * @param keymap * @return * @throws Exception * / สตริงคงที่สาธารณะ getPrivateKey (แผนที่ <String, Object> KEYMAP) โยนข้อยกเว้น {key key = (key) keymap.get (private_key); ส่งคืน EncryptBase64 (key.getEncoded ()); // base64 การเข้ารหัสคีย์ส่วนตัว}/** * รับคีย์สาธารณะ * * @param keymap * @return * @throws Exception */สตริงคงที่สาธารณะ getPublickey (แผนที่ <สตริงวัตถุ> keymap) โยนข้อยกเว้น {key key = (key) keymap.get (public_key); ส่งคืน EncryptBase64 (key.getEncoded ()); // base64 การเข้ารหัสคีย์สาธารณะ}/** * ใช้คีย์ส่วนตัวเพื่อลงนามข้อมูลแบบดิจิทัล * @param ข้อมูลที่เข้ารหัสข้อมูล * @param ส่วนตัวคีย์ส่วนตัว - base64 เข้ารหัส * @return * @throws Exception */ข้อมูลสตริงสาธารณะ ไบต์ [] keybytes = decryptBase64 (PrivateKey); PKCS8ENCODEDKEYSPEC KEYSPEC = ใหม่ PKCS8ENCODEDKEYSPEC (keyBytes); KeyFactory Factory = keyFactory.getInstance (key_algorithm); PrivateKey Prikey = Factory.GeneratePrivate (KeySPEC); // สร้างคีย์ส่วนตัว // ข้อมูลตัวเลขด้วยลายเซ็นรหัสส่วนตัว = Signature.getInstance (Signature_Algorithm); Signature.initsign (Prikey); signature.update (ข้อมูล); ส่งคืน EncryptBase64 (Signature.Sign ()); } / *** การเข้ารหัส Base64Encoder* @param data data ที่จะเข้ารหัส* @return String encrypted* / สตริงคงที่ส่วนตัว EncryptBase64 (BYTE [] ข้อมูล) {base64Encoder encoder = ใหม่ BASE644ENCODER (); string encode = encoder.encode (data); return encode; } / *** base64decoder decrypt* @param สตริงข้อมูลที่จะถอดรหัส* @return decrypted byte []* @throws exception* / private static byte [] decryptBase64 (ข้อมูลสตริง) โยนข้อยกเว้น Byte [] buffer = decoder.decodeBuffer (ข้อมูล); คืนบัฟเฟอร์; } / *** ตรวจสอบลายเซ็นดิจิตอล* @param data ข้อมูลเข้ารหัส* @param publicKey* @param Sign Signature Digital* @return* @throws Exception* / Public Static Boolean ยืนยัน (BYTE [] ข้อมูล, String PublicKey, String Sign) X509ENCODEDKEYSPEC KEYSPEC = ใหม่ X509ENCODEDKEYSPEC (KeyBytes); keyFactory keyFactory = keyFactory.getInstance (key_algorithm); PublicKey Pubkey = keyFactory.generatePublic (KeySpec); ลายเซ็น = Signature.GetInstance (Signature_Algorithm); Signature.initverify (Pubkey); signature.update (ข้อมูล); ส่งคืน signature.Verify (DECRYPTBASE64 (SIGN)); // ตรวจสอบลายเซ็น}}