Score:1

ผลการยืนยันของ (EC-) Diffie-Hellman

ธง in

ฉันได้รับรหัสสาธารณะจาก JSON

ตัวอย่างเช่น ฉันมี 4 คีย์: 2 คีย์สาธารณะและ 2 คีย์ส่วนตัว

สาธารณะ A : co2D0pNxZJIeQ4RZlCRJYBDzNXSLluETdztid0M+HGzN1uGJ4JWZsenjWgRrmkLh3yqHQqzOBMl/wHVH97A6+g==

ส่วนตัว A : TXxii5Ka8LMvuc9arHu63qTmNKxGlgti+wpR3YhBGew=

B สาธารณะ : nUblC+OKdl94iBiWk0941wmYBiMt7C90CjOJPI2BPr8K7xGuC1XsR5DtwFCoM3Iew2BjBG+5SqrYwAPTJF7gdA==

ส่วนตัว B : sm6V7+hChvkFSeLNoR+5tItiX8gH5tT47xBkFaV6SDU=

ฉันไม่สามารถทำ การแลกเปลี่ยน ECDH จาก กุญแจสาธารณะ ก และ ก รหัสส่วนตัว B ที่ฉันได้รับใน JSON

ฉันจะตรวจสอบได้อย่างไร: (คีย์สาธารณะ A + คีย์ส่วนตัว B) == (คีย์สาธารณะ B + คีย์ส่วนตัว A) ?

Michael Fehr avatar
gb flag
คีย์ในไฟล์ JSON เป็นคีย์ที่เข้ารหัส Base64 และมักจะนำเข้าได้ด้วยข้อมูลจำเพาะของคีย์จากนั้นสร้างความลับที่ใช้ร่วมกันโดยใช้ [คีย์สาธารณะ A + คีย์ส่วนตัว B] และ [คีย์สาธารณะ B + คีย์ส่วนตัว A] และหากความลับมีค่าเท่ากัน แสดงว่าคุณได้ตรวจสอบแล้วว่ามีคีย์ทำงาน 2 คู่ โปรดแก้ไขคำถามของคุณและเพิ่มโค้ด เนื่องจาก Stackoverflow ไม่ใช่บริการเขียนโค้ดฟรี ขอบคุณ
Maarten Bodewes avatar
in flag
โปรดทราบว่าการแลกเปลี่ยน ECDH ไม่ใช้ "การบวก" แต่ใช้การคูณจุดเป็นโครงสร้างทางคณิตศาสตร์พื้นฐาน
fgrieu avatar
ng flag
คำแนะนำ: ถอดรหัส Base64, ออกกฎว่าเนื้อหาคือ ASN.1, คาดเดาอย่างไม่แน่นอนว่าเป็นไบต์ดิบของ big-endian, สรุปจากขนาดที่คีย์สาธารณะอาจมี X และ Y ต่อกัน, ใช้ความซ้ำซ้อนสูงที่นั่นเพื่อ (หวังว่าจะ) คิดออก เส้นโค้งทั่วไป (อาจเป็นหนึ่งใน [เหล่านี้](https://www.secg.org/sec2-v2.pdf#subsection.2.4)) และกาเครื่องหมาย $a\,B=b\,A$ ตามที่ถาม หรือตรวจสอบว่า $a\,G=A$ และ $b\,G=B$ (นั่นคือคีย์สาธารณะและคีย์ส่วนตัวตรงกัน) ซึ่งจะพิสูจน์ $a\,B=b\,A$ โดยไม่ต้องคำนวณเพิ่มเติม [ข้อมูลอ้างอิง](https://www.secg.org/sec1-v2.pdf#subsubsection.2.2.1) อาจช่วยได้ (YMMV)
Score:6
ธง in

โดยปกติผลลัพธ์ของการคำนวณ Diffie-Hellman (เส้นโค้งวงรี) เรียกว่าความลับหลัก คีย์หลักนี้มักใช้เป็นข้อมูลคีย์ข้อมูลเข้า (IKM) สำหรับ Key Derivation Function (KDF) การใช้คีย์หลายคีย์ของ KDF สามารถรับมาจากข้อมูลลับหลัก สิ่งที่คุณกำลังมองหาเรียกว่า "โครงสร้างหลัก"

มีหลายวิธีในการยืนยันคีย์สมมาตร:

  1. หนึ่งในคีย์เหล่านี้สามารถใช้เป็นอินพุตสำหรับโปรโตคอลการตอบสนองความท้าทาย โปรโตคอลการตอบสนองความท้าทายเป็นวิธีการแบบสมมาตรเพื่อตรวจสอบว่าเอนทิตีมีสิทธิ์เข้าถึงรหัสลับที่ถูกต้อง

  2. อีกวิธีหนึ่งคือการใช้คีย์เป็นอินพุตไปยัง MAC ผ่านสตริงที่ทั้งสองฝ่ายรู้จัก ด้วยวิธีนี้ MAC แสดงให้เห็นว่าเอนทิตีสามารถเข้าถึงคีย์ที่ถูกต้องได้ ตัวอย่างเช่น TLS (1.3) ใช้ MAC ในการจับมือทั้งหมดในข้อความ "เสร็จสิ้น" สุดท้ายของการจับมือกัน:

    ที่เสร็จเรียบร้อย: MAC (รหัสตรวจสอบข้อความ) ทั่วทั้ง จับมือ ข้อความนี้ ให้การยืนยันคีย์, ผูก ข้อมูลประจำตัวของอุปกรณ์ปลายทางไปยังคีย์ที่แลกเปลี่ยน และในโหมด PSK ด้วย ตรวจสอบการจับมือ [ข้อ 4.4.4]

  3. คุณสามารถจินตนาการได้ว่าฝ่ายหนึ่งสามารถลงนามในความลับที่เป็นผลลัพธ์และส่งลายเซ็นไปยังอีกฝ่ายหนึ่งได้

  4. สุดท้าย การยืนยันว่าคีย์ที่เป็นผลลัพธ์และข้อมูลลับนั้นเหมือนกันสามารถดำเนินการโดยปริยายได้เมื่อข้อความยืนยันตัวตนแรกถูกส่งจากฝ่ายหนึ่งไปยังอีกฝ่ายหนึ่ง อย่างไรก็ตาม โดยทั่วไปจะหลีกเลี่ยงสิ่งนี้ เนื่องจากหมายความว่าคุณไม่สามารถแยกความแตกต่างระหว่างข้อผิดพลาดในการรับส่งข้อมูลและแฮนด์เชค ดังนั้นจึงสามารถเล่น Merry Hell ในการใช้งานโปรโตคอลได้

หมายเหตุ:

  • หากคุณยืนยันคีย์เดียว ความถูกต้องของข้อมูลลับและคีย์ที่ได้รับอื่นๆ จะได้รับการยืนยันด้วย (ยกเว้นข้อผิดพลาดในการนำไปใช้)
  • อาจเป็นไปได้ว่ารหัสสาธารณะ (แบบคงที่) ของ DH สามารถเชื่อถือได้โดยวิธีอื่น ซึ่งในกรณีนี้ฝ่ายที่รับรองความถูกต้องอาจไม่จำเป็นต้องมีการยืนยันเพิ่มเติมเกี่ยวกับความลับที่เป็นผลลัพธ์ เฉพาะบุคคลที่ไม่ได้รับการรับรองความถูกต้องเท่านั้นที่จะต้องส่งคำตอบท้าทาย ค่า MAC หรือลายเซ็น
Score:0
ธง in

นี่คือวิธีที่ฉันแก้ปัญหาของฉัน:

คีย์ของฉันในสตริง:

สาธารณะ A : co2D0pNxZJIeQ4RZlCRJYBDzNXSLluETdztid0M+HGzN1uGJ4JWZsenjWgRrmkLh3yqHQqzOBMl/wHVH97A6+g==

ส่วนตัว A : TXxii5Ka8LMvuc9arHu63qTmNKxGlgti+wpR3YhBGew=

B สาธารณะ : nUblC+OKdl94iBiWk0941wmYBiMt7C90CjOJPI2BPr8K7xGuC1XsR5DtwFCoM3Iew2BjBG+5SqrYwAPTJF7gdA==

ส่วนตัว B : sm6V7+hChvkFSeLNoR+5tItiX8gH5tT47xBkFaV6SDU=

ฟังก์ชั่นเพื่อรับรหัสส่วนตัว:

สาธารณะคง PrivateKey getPrivateKey (ไบต์ [] encodedPrivateKey) {
   BigInteger s = BigInteger ใหม่ (1, encodedPrivateKey);
   ECNamedCurveParameterSpec ecCurve = ECNamedCurveTable.getParameterSpec("secp256r1");
   ECParameterSpec ecParameterSpec = ใหม่ ECNamedCurveSpec("secp256r1", ecCurve.getCurve(), ecCurve.getG(), ecCurve.getN(), ecCurve.getH(), ecCurve.getSeed());
   ECPrivateKeySpec privateKeySpec = ใหม่ ECPrivateKeySpec(s, ecParameterSpec);
   พยายาม {
       KeyFactory keyFactory = KeyFactory.getInstance("EC");
       ส่งคืน keyFactory.generatePrivate (privateKeySpec);
    } catch (NoSuchAlgorithmException | InvalidKeySpecException จ) {
        e.printStackTrace();
        ส่งคืน null;
   }
}

PublicKey แบบคงที่สาธารณะ rawToEncodedECPublicKey (String curveName, ไบต์ [] rawBytes) โยน NoSuchAlgorithmException, InvalidKeySpecException, InvalidParameterSpecException {
   KeyFactory kf = KeyFactory.getInstance("EC");
   ไบต์ [] x = Arrays.copyOfRange (rawBytes, 0, rawBytes.length/2);
   ไบต์ [] y = Arrays.copyOfRange (rawBytes, rawBytes.length/2, rawBytes.length);
   ECPoint w = ECPoint ใหม่ (BigInteger ใหม่ (1,x), BigInteger ใหม่ (1,y));
   ส่งคืน kf.generatePublic (ใหม่ ECPublicKeySpec (w, ecParameterSpecForCurve (curveName)));
}

สาธารณะคงที่ java.security.spec.ECParameterSpec ecParameterSpecForCurve (String curveName) โยน NoSuchAlgorithmException, InvalidParameterSpecException {
   AlgorithmParameters params = AlgorithmParameters.getInstance("EC");
   params.init (ECGenParameterSpec ใหม่ (curveName));
   กลับ params.getParameterSpec (ECParameterSpec.class);
}

เราจำเป็นต้องสร้างคีย์ 2 คู่ผ่านคีย์ public/private ในสตริง และตรวจสอบว่าทั้งคู่เท่ากันหรือไม่ :

ไบต์ [] cle_publique_a_decode = Base64.getDecoder().decode(cle_publique_a);
ไบต์ [] cle_privee_a_decode = Base64.getDecoder().ถอดรหัส(cle_privee_a);
ไบต์ [] cle_publique_b_decode = Base64.getDecoder().decode(cle_publique_b);
ไบต์ [] cle_privee_b_decode = Base64.getDecoder().ถอดรหัส(cle_privee_b);

พยายาม {
     PublicKey PublicKeyA = rawToEncodedECPublicKey("secp256r1",cle_publique_a_decode);
     PublicKey PublicKeyB = rawToEncodedECPublicKey("secp256r1",cle_publique_b_decode);

     PrivateKey PrivateKeyA = getPrivateKey(cle_privee_a_decode);
     PrivateKey PrivateKeyB = getPrivateKey(cle_privee_b_decode);

     // ความลับ #1
     // PrivateKeyA + PublicKeyB = createSecret
     KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
     keyAgreement.init (PrivateKeyA);
     keyAgreement.doPhase (PublicKeyB, จริง);
     ไบต์ [] createSecret = keyAgreement.generateSecret ();
     สตริง base64_generateSecret = Base64.getEncoder().encodeToString(generateSecret);

     // ความลับ #2
     // PrivateKeyB + PublicKeyA = createSecret2
     KeyAgreement keyAgreement2 = KeyAgreement.getInstance("ECDH");
     keyAgreement.init (คีย์ส่วนตัว B);
     keyAgreement.doPhase (PublicKeyA จริง);
     ไบต์ [] createSecret2 = keyAgreement.generateSecret ();
     สตริง base64_generateSecret2 = Base64.getEncoder().encodeToString(generateSecret);

     // เปรียบเทียบ 2 ความลับ
     // (คีย์สาธารณะ A + คีย์ส่วนตัว B) == (คีย์สาธารณะ B + คีย์ส่วนตัว A)
     ถ้า (base64_generateSecret.equals (base64_generateSecret2)){
          // ดี : ความลับเหมือนกัน
          // ดำเนินต่อ..
     }
     อื่น{
          // ไม่ดี : ความลับต่างกัน
     }
}
จับ{
     โยนใหม่ IllegalArgumentException(e.getMessage(), e);
}

คีย์เท่ากัน ฉันเริ่มเข้ารหัสได้

Maarten Bodewes avatar
in flag
แนวคิดทั้งหมดของ DH คือคุณสร้างความลับในสองตำแหน่ง คุณไม่สามารถเปรียบเทียบความลับได้โดยตรงโดยใช้ "เท่ากับ" เพราะนั่นหมายความว่าคุณสามารถคัดลอกค่าจากที่หนึ่งไปยังอีกที่หนึ่งได้ ถ้าทำได้ก็ไม่ต้องใช้ DH

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา