paint-brush
บัญชี zkEmail ใน Noir & Aztec - ตอนที่ 1โดย@oleh
578 การอ่าน
578 การอ่าน

บัญชี zkEmail ใน Noir & Aztec - ตอนที่ 1

โดย Oleh Misarosh11m2024/09/13
Read on Terminal Reader

นานเกินไป; อ่าน

บัญชี zkEmail คือบัญชีสัญญาอัจฉริยะที่อนุญาตให้ผู้ใช้ยืนยันธุรกรรมโดยการตอบกลับอีเมล
featured image - บัญชี zkEmail ใน Noir & Aztec - ตอนที่ 1
Oleh Misarosh HackerNoon profile picture
0-item
1-item

ขอขอบคุณทีมงาน Mach34 เป็นอย่างมากสำหรับเวอร์ชันแรกของ zkemail ใน Noir

การแนะนำ

บัญชี zkEmail เป็นบัญชีสัญญาอัจฉริยะที่อนุญาตให้ผู้ใช้ยืนยันธุรกรรมโดยการตอบกลับอีเมล บัญชีนี้ทำงานอย่างไร ข้อความอีเมลแต่ละข้อความได้รับการลงนามโดยผู้ให้บริการอีเมลของผู้ใช้ (เช่น iCloud, Gmail หรือ ProtonMail) บัญชีสัญญาอัจฉริยะของผู้ใช้จะตรวจสอบลายเซ็นบนเชนและดำเนินการธุรกรรมหากลายเซ็นนั้นถูกต้อง นอกเหนือจากการตรวจสอบลายเซ็นแล้ว การตรวจสอบลายเซ็นยังมีความสำคัญอีกด้วย


  1. อีเมลถูกส่งจากที่อยู่อีเมลของผู้ใช้
  2. มันถูกส่งไปยังที่อยู่อีเมลของผู้ถ่ายทอดแล้ว
  3. อีเมลมีหัวเรื่องที่ถูกต้อง (ซึ่งรวมถึงคำอธิบายข้อมูลการโทรหรือการชำระเงิน)

ตัวอย่าง

อลิซส่งอีเมลต่อไปนี้ไปยังผู้ส่งต่อ:

 from: [email protected] to: [email protected] subject: Send 10 ETH to vitalik.eth DKIM-Signature: /* signature by icloud.com */ /* body is not relevant */

สังเกตส่วนหัว DKIM-Signature ไหม มันคือลายเซ็นที่สร้างขึ้นโดยคีย์ส่วนตัวของ iCloud บทความที่เหลือจะอธิบายดังนี้:


  1. ผู้ให้บริการอีเมล์ลงนามอะไรบ้าง
  2. วิธีการรับคีย์สาธารณะของผู้ให้บริการอีเมล
  3. วิธีการตรวจสอบลายเซ็นใน Noir

ลายเซ็น

ลายเซ็น DKIM ถูกสร้างขึ้นโดยผู้ให้บริการอีเมลที่ลงนามส่วนหัวย่อยตามลำดับและรูปแบบมาตรฐานที่ถูกต้อง มาดูส่วนหัวลายเซ็น DKIM กัน:

 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1693038337; bh=7xQMDuoVVU4m0W0WRVSrVXMeGSIASsnucK9dJsrc+vU=; h=from:Content-Type:Mime-Version:Subject:Message-Id:Date:to; b=EhLyVPpKD7d2/+h1nrnu+iEEBDfh6UWiAf9Y5UK+aPNLt3fAyEKw6Ic46v32NOcZD M/zhXWucN0FXNiS0pz/QVIEy8Bcdy7eBZA0QA1fp8x5x5SugDELSRobQNbkOjBg7Mx VXy7h4pKZMm/hKyhvMZXK4AX9fSoXZt4VGlAFymFNavfdAeKgg/SHXLds4lOPJV1wR 2E21g853iz5m/INq3uK6SQKzTnz/wDkdyiq90gC0tHQe8HpDRhPIqgL5KSEpuvUYmJ wjEOwwHqP6L3JfEeROOt6wyuB1ah7wgRvoABOJ81+qLYRn3bxF+y1BC+PwFd5yFWH5 Ry43lwp1/3+sA==

ประกอบด้วยคู่คีย์-ค่าที่คั่นด้วยเครื่องหมายเซมิโคลอน ส่วนที่สำคัญได้แก่ a= และ b= มาแยกย่อยกัน:


  • a= คืออัลกอริทึมที่ใช้ในการลงนามข้อความ ในกรณีนี้คือ rsa-sha256
  • b= คือลายเซ็นต์ในรหัสแบบ base64

ลงนามอะไรบ้างคะ?

ส่วนหัวอีเมลจะถูกเรียงลำดับและกำหนดเป็นมาตรฐานก่อนลงนาม ลำดับของส่วนหัวจะระบุโดยพารามิเตอร์ h= ของส่วนหัว DKIM-Signature จากนั้นส่วนหัวจะถูกแปลงเป็นตัวพิมพ์เล็ก ลบช่องว่างพิเศษออก แล้วจึงเชื่อมด้วยอักขระ \r\n มาดูส่วนหัวก่อนกำหนดเป็นมาตรฐานกัน:


 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1693038337; bh=7xQMDuoVVU4m0W0WRVSrVXMeGSIASsnucK9dJsrc+vU=; h=from:Content-Type:Mime-Version:Subject:Message-Id:Date:to; b=EhLyVPpKD7d2/+h1nrnu+iEEBDfh6UWiAf9Y5UK+aPNLt3fAyEKw6Ic46v32NOcZD M/zhXWucN0FXNiS0pz/QVIEy8Bcdy7eBZA0QA1fp8x5x5SugDELSRobQNbkOjBg7Mx VXy7h4pKZMm/hKyhvMZXK4AX9fSoXZt4VGlAFymFNavfdAeKgg/SHXLds4lOPJV1wR 2E21g853iz5m/INq3uK6SQKzTnz/wDkdyiq90gC0tHQe8HpDRhPIqgL5KSEpuvUYmJ wjEOwwHqP6L3JfEeROOt6wyuB1ah7wgRvoABOJ81+qLYRn3bxF+y1BC+PwFd5yFWH5 Ry43lwp1/3+sA== from: [email protected] Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3731.500.231\)) Subject: Hello Message-Id: <[email protected]> Date: Sat, 26 Aug 2023 12:25:22 +0400 to: [email protected]


และหลังจากการกำหนดมาตรฐานแล้ว:

 from:[email protected]\r\ncontent-type:text/plain; charset=us-ascii\r\nmime-version:1.0 (Mac OS X Mail 16.0 \\(3731.500.231\\))\r\nsubject:Hello\r\nmessage-id:<[email protected]>\r\ndate:Sat, 26 Aug 2023 12:25:22 +0400\r\nto:[email protected]\r\ndkim-signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1693038337; bh=7xQMDuoVVU4m0W0WRVSrVXMeGSIASsnucK9dJsrc+vU=; h=from:Content-Type:Mime-Version:Subject:Message-Id:Date:to; b=


โปรดทราบว่าส่วนหัว DKIM-Signature จะรวมอยู่ในส่วนหัวที่เป็นมาตรฐานด้วย แต่ไม่มีค่าพารามิเตอร์ b= มีเพียงคีย์เท่านั้นที่รวมอยู่


เมื่อส่งอีเมลแล้ว iCloud.com จะลงนามในส่วนหัวที่กำหนดมาตรฐานด้วยคีย์ส่วนตัว จากนั้นลายเซ็นจะรวมอยู่ในส่วนหัว DKIM-Signature โดยเฉพาะในพารามิเตอร์ b=

คีย์สาธารณะของผู้ให้บริการอีเมล์

2 คำถาม:

  1. จะรับคีย์สาธารณะของผู้ให้บริการอีเมล์ได้อย่างไร?
  2. จะตรวจสอบลายเซ็นใน Noir ได้อย่างไร?


หากคุณดูที่ส่วนหัว DKIM-Signature จากด้านบน คุณจะสังเกตเห็นพารามิเตอร์ 2 ตัว: d=icloud.com และ s=1a1hai ซึ่งก็คือ d และตัวเลือก s ของผู้ให้บริการอีเมล เราสามารถรับคีย์สาธารณะได้โดยสอบถามระเบียน DNS เฉพาะ: {s}._domainkey.{d} ในกรณีนี้ เราต้องสอบถาม 1a1hai._domainkey.icloud.com มาสอบถามโดยใช้คำสั่ง dig :

 dig +short TXT 1a1hai._domainkey.icloud.com


เราได้รับการตอบสนองดังต่อไปนี้:

 "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1ZEfbkf4TbO2TDZI67WhJ6G8Dwk3SJyAbBlE/QKdyXFZB4HfEU7AcuZBzcXSJFE03DlmyOkUAmaaR8yFlwooHyaKRLIaT3epGlL5YGowyfItL" "ly2k0Jj0IOICRxWrB378b7qMeimE8KlH1UNaVpRTTi0XIYjIKAOpTlBmkM9a/3Rl4NWy8pLYApXD+WCkYxPcxoAAgaN8osqGTCJ5r+VHFU7Wm9xqq3MZmnfo" "0bzInF4UajCKjJAQa+HNuh95DWIYP/wV77/PxkEakOtzkbJMlFJiK/hMJ+HQUvTbtKW2s+t4uDK8DI16Rotsn6e0hS8xuXPmVte9ZzplD0fQgm2qwIDAQAB"


ส่วนที่น่าสนใจคือพารามิเตอร์ p= โปรดทราบว่าพารามิเตอร์นี้ถูกแบ่งออกเป็นหลายบรรทัดเครื่องหมายคำพูด ดังนั้นเราต้องต่อกัน ผลลัพธ์คือ:

 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1ZEfbkf4TbO2TDZI67WhJ6G8Dwk3SJyAbBlE/QKdyXFZB4HfEU7AcuZBzcXSJFE03DlmyOkUAmaaR8yFlwooHyaKRLIaT3epGlL5YGowyfItLly2k0Jj0IOICRxWrB378b7qMeimE8KlH1UNaVpRTTi0XIYjIKAOpTlBmkM9a/3Rl4NWy8pLYApXD+WCkYxPcxoAAgaN8osqGTCJ5r+VHFU7Wm9xqq3MZmnfo0bzInF4UajCKjJAQa+HNuh95DWIYP/wV77/PxkEakOtzkbJMlFJiK/hMJ+HQUvTbtKW2s+t4uDK8DI16Rotsn6e0hS8xuXPmVte9ZzplD0fQgm2qwIDAQAB


นี่คือคีย์สาธารณะของผู้ให้บริการอีเมล ( iCloud.com ) ที่เข้ารหัสด้วยรหัส base64 เราจะใช้รหัสนี้ในภายหลังเพื่อยืนยันลายเซ็นใน Noir

วงจรนัวร์

เนื่องจากข้อจำกัดของวงจร ZK เราจึงต้องใช้การใช้งาน RSA ที่ได้รับการปรับให้เหมาะสมโดยเฉพาะและตัวเลขขนาดใหญ่ที่จัดทำโดยทีม Noir: https://github.com/noir-lang/noir_rsa


ติดตั้งใน Nargo.toml:

 [dependencies] noir_rsa = { tag = "v0.2", git = "https://github.com/noir-lang/noir_rsa" }


ตอนนี้มาดูวงจร Noir เพื่อการตรวจสอบกัน:

 use noir_rsa::bignum::BigNum; use noir_rsa::bignum::runtime_bignum::BigNumInstance; use noir_rsa::bignum::fields::Params2048; use noir_rsa::RSA; global PUBKEY_LIMBS_LEN: u32 = 18; global SIGNATURE_LIMBS_LEN: u32 = 18; type BN2048 = BigNum<18, Params2048>; type RSA2048 = RSA<BN2048, BigNumInstance<18, Params2048>, 256>; global rsa: RSA2048 = RSA {}; fn verify_email<let MAX_HEADERS_LEN: u32>( headers: [u8; MAX_HEADERS_LEN], headers_len: u32, pubkey_limbs: [Field; PUBKEY_LIMBS_LEN], pubkey_redc_limbs: [Field; PUBKEY_LIMBS_LEN], signature: [Field; SIGNATURE_LIMBS_LEN] ) -> bool { let signature: BN2048 = BigNum::from_array(signature); let pubkey: BigNumInstance<18, Params2048> = BigNumInstance::new(pubkey_limbs, pubkey_redc_limbs); let headers_hash = std::hash::sha256_var(headers, headers_len as u64); rsa.verify_sha256_pkcs1v15(pubkey, headers_hash, signature) }


ฉันจะข้ามการนำเข้าและการกำหนดประเภทเพื่อความกระชับ (ใครจะสนใจล่ะ แค่คัดลอกแล้ววางมัน) มาดูพารามิเตอร์ verify_email กัน:

  • headers : ส่วนหัวที่กำหนดมาตรฐานเป็นอาร์เรย์ของไบต์ มีความยาวคงที่และต้องเติม 0 ไว้ที่ท้าย
  • headers_len : ความยาวจริงของส่วนหัว
  • pubkey_limbs & pubkey_redc_limbs : คีย์สาธารณะของผู้ให้บริการอีเมลที่เข้ารหัสโดยเฉพาะสำหรับ Noir
  • signature : ลายเซ็นของผู้ให้บริการอีเมลที่เข้ารหัสเฉพาะสำหรับ Noir


ในฟังก์ชัน เราจะแปลงลายเซ็นและคีย์สาธารณะเป็นอินสแตนซ์จำนวนมากก่อน จากนั้นเราจะแฮชส่วนหัวมาตรฐานด้วย sha256 และตรวจสอบลายเซ็นด้วยคีย์สาธารณะและแฮช

 let signature: BN2048 = BigNum::from_array(signature); let pubkey: BigNumInstance<18, Params2048> = BigNumInstance::new(pubkey_limbs, pubkey_redc_limbs); let headers_hash = std::hash::sha256_var(headers, headers_len as u64); rsa.verify_sha256_pkcs1v15(pubkey, headers_hash, signature)


หากการตรวจสอบสำเร็จ ฟังก์ชันจะส่งคืน true หากไม่เช่นนั้นจะส่งคืน false

จากสตริงอีเมลดิบสู่อินพุตของ Noir

ตอนนี้เรามีวงจร Noir แล้ว เราจะแปลงสตริงอีเมลแบบดิบให้เป็นอินพุตที่มีโครงสร้างสำหรับวงจรได้อย่างไร


มาเริ่มกันที่ส่วนหัว ฉันจะใช้ mailparser เพื่อแยกวิเคราะห์อีเมลและ dkim เพื่อแยกส่วนหัวที่เป็นมาตรฐานออกมา วิเคราะห์อีเมล:

 import DKIM from "dkim"; import { simpleParser } from "mailparser"; async function canonicalizeHeaders(emailStr: string) { const email = await simpleParser(emailStr); const dkimHeader = email.headers.get("dkim-signature").params; const canonicalHeaders = DKIM.processHeader( email.headerLines.map((x) => x.line), dkimHeader.h.split(":").map((x) => x.trim()), "relaxed", ); const signatureBase64 = dkimHeader.b.replace(/\s/g, ""); return { canonicalHeaders, signatureBase64 }; }


ตอนนี้ทดสอบมัน:

 const { canonicalHeaders, signatureBase64 } = await canonicalizeHeaders( String.raw` DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1693038337; bh=7xQMDuoVVU4m0W0WRVSrVXMeGSIASsnucK9dJsrc+vU=; h=from:Content-Type:Mime-Version:Subject:Message-Id:Date:to; b=EhLyVPpKD7d2/+h1nrnu+iEEBDfh6UWiAf9Y5UK+aPNLt3fAyEKw6Ic46v32NOcZD M/zhXWucN0FXNiS0pz/QVIEy8Bcdy7eBZA0QA1fp8x5x5SugDELSRobQNbkOjBg7Mx VXy7h4pKZMm/hKyhvMZXK4AX9fSoXZt4VGlAFymFNavfdAeKgg/SHXLds4lOPJV1wR 2E21g853iz5m/INq3uK6SQKzTnz/wDkdyiq90gC0tHQe8HpDRhPIqgL5KSEpuvUYmJ wjEOwwHqP6L3JfEeROOt6wyuB1ah7wgRvoABOJ81+qLYRn3bxF+y1BC+PwFd5yFWH5 Ry43lwp1/3+sA== from: [email protected] Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3731.500.231\)) Subject: Hello Message-Id: <[email protected]> Date: Sat, 26 Aug 2023 12:25:22 +0400 to: [email protected] `.trim(), ); console.log("signature:", signatureBase64); console.log(); console.log("headers:", JSON.stringify(canonicalHeaders));


เราจะได้ผลลัพธ์ดังต่อไปนี้:

 signature: EhLyVPpKD7d2/+h1nrnu+iEEBDfh6UWiAf9Y5UK+aPNLt3fAyEKw6Ic46v32NOcZDM/zhXWucN0FXNiS0pz/QVIEy8Bcdy7eBZA0QA1fp8x5x5SugDELSRobQNbkOjBg7MxVXy7h4pKZMm/hKyhvMZXK4AX9fSoXZt4VGlAFymFNavfdAeKgg/SHXLds4lOPJV1wR2E21g853iz5m/INq3uK6SQKzTnz/wDkdyiq90gC0tHQe8HpDRhPIqgL5KSEpuvUYmJwjEOwwHqP6L3JfEeROOt6wyuB1ah7wgRvoABOJ81+qLYRn3bxF+y1BC+PwFd5yFWH5Ry43lwp1/3+sA== headers: "from:[email protected]\r\ncontent-type:text/plain; charset=us-ascii\r\nmime-version:1.0 (Mac OS X Mail 16.0 \\(3731.500.231\\))\r\nsubject:Hello\r\nmessage-id:<[email protected]>\r\ndate:Sat, 26 Aug 2023 12:25:22 +0400\r\nto:[email protected]\r\ndkim-signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1693038337; bh=7xQMDuoVVU4m0W0WRVSrVXMeGSIASsnucK9dJsrc+vU=; h=from:Content-Type:Mime-Version:Subject:Message-Id:Date:to; b="


และแปลงเป็นไบต์:

 const canonicalHeadersBytes = Array.from( Buffer.from(canonicalHeaders, "utf-8"), ); console.log( "canonicalHeadersBytes:", "[", canonicalHeadersBytes.join(", "), "]", );


เอาท์พุต:

 canonicalHeadersBytes: [ 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 115, 45, 97, 115, 99, 105, 105, 13, 10, 109, 105, 109, 101, 45, 118, 101, 114, 115, 105, 111, 110, 58, 49, 46, 48, 32, 40, 77, 97, 99, 32, 79, 83, 32, 88, 32, 77, 97, 105, 108, 32, 49, 54, 46, 48, 32, 92, 40, 51, 55, 51, 49, 46, 53, 48, 48, 46, 50, 51, 49, 92, 41, 41, 13, 10, 115, 117, 98, 106, 101, 99, 116, 58, 72, 101, 108, 108, 111, 13, 10, 109, 101, 115, 115, 97, 103, 101, 45, 105, 100, 58, 60, 56, 70, 56, 49, 57, 68, 51, 50, 45, 66, 54, 65, 67, 45, 52, 56, 57, 68, 45, 57, 55, 55, 70, 45, 52, 51, 56, 66, 66, 67, 52, 67, 65, 66, 50, 55, 64, 109, 101, 46, 99, 111, 109, 62, 13, 10, 100, 97, 116, 101, 58, 83, 97, 116, 44, 32, 50, 54, 32, 65, 117, 103, 32, 50, 48, 50, 51, 32, 49, 50, 58, 50, 53, 58, 50, 50, 32, 43, 48, 52, 48, 48, 13, 10, 116, 111, 58, 122, 107, 101, 119, 116, 101, 115, 116, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109, 13, 10, 100, 107, 105, 109, 45, 115, 105, 103, 110, 97, 116, 117, 114, 101, 58, 118, 61, 49, 59, 32, 97, 61, 114, 115, 97, 45, 115, 104, 97, 50, 53, 54, 59, 32, 99, 61, 114, 101, 108, 97, 120, 101, 100, 47, 114, 101, 108, 97, 120, 101, 100, 59, 32, 100, 61, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 59, 32, 115, 61, 49, 97, 49, 104, 97, 105, 59, 32, 116, 61, 49, 54, 57, 51, 48, 51, 56, 51, 51, 55, 59, 32, 98, 104, 61, 55, 120, 81, 77, 68, 117, 111, 86, 86, 85, 52, 109, 48, 87, 48, 87, 82, 86, 83, 114, 86, 88, 77, 101, 71, 83, 73, 65, 83, 115, 110, 117, 99, 75, 57, 100, 74, 115, 114, 99, 43, 118, 85, 61, 59, 32, 104, 61, 102, 114, 111, 109, 58, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 77, 105, 109, 101, 45, 86, 101, 114, 115, 105, 111, 110, 58, 83, 117, 98, 106, 101, 99, 116, 58, 77, 101, 115, 115, 97, 103, 101, 45, 73, 100, 58, 68, 97, 116, 101, 58, 116, 111, 59, 32, 98, 61 ]


บันทึกเอาท์พุตเหล่านี้ไว้เพื่อใช้ในภายหลัง


ตอนนี้มาแปลงคีย์สาธารณะและลายเซ็นของผู้ให้บริการอีเมลเป็น Noir big number limbs กัน มี ไลบรารี Rust อย่างเป็นทางการ เพียงไลบรารีเดียวเท่านั้น แต่คุณโชคดีเพราะฉันคอมไพล์เป็น wasm แล้วเผยแพร่ไปยัง npm มาติดตั้งกันเลย:

 npm i @shieldswap/email_account_utils_rs


ยอมรับคีย์สาธารณะและลายเซ็นใน base64 และส่งคืนคีย์สาธารณะและลายเซ็นในรูปแบบ JSON:

 import init, { get_limbs } from "@shieldswap/email_account_utils_rs"; await init(); // initialize the wasm module // base64 encoded public key from email provider const publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1ZEfbkf4TbO2TDZI67WhJ6G8Dwk3SJyAbBlE/QKdyXFZB4HfEU7AcuZBzcXSJFE03DlmyOkUAmaaR8yFlwooHyaKRLIaT3epGlL5YGowyfItLly2k0Jj0IOICRxWrB378b7qMeimE8KlH1UNaVpRTTi0XIYjIKAOpTlBmkM9a/3Rl4NWy8pLYApXD+WCkYxPcxoAAgaN8osqGTCJ5r+VHFU7Wm9xqq3MZmnfo0bzInF4UajCKjJAQa+HNuh95DWIYP/wV77/PxkEakOtzkbJMlFJiK/hMJ+HQUvTbtKW2s+t4uDK8DI16Rotsn6e0hS8xuXPmVte9ZzplD0fQgm2qwIDAQAB"; const { public_key_limbs, public_key_redc_limbs, signature_limbs } = JSON.parse( get_limbs(publicKey, signatureBase64), ); console.log("public_key_limbs", "[" + public_key_limbs.join(",") + "]"); console.log( "public_key_redc_limbs", "[" + public_key_redc_limbs.join(",") + "]", ); console.log("signature_limbs", "[" + signature_limbs.join(",") + "]");


ตอนนี้เรามีข้อมูลที่จำเป็นทั้งหมดสำหรับการตรวจสอบลายเซ็นแล้ว มาเริ่มกันเลย ฉันจะคัดลอกและวางข้อมูลที่สร้างโดย JavaScript ลงในการทดสอบ Noir เพื่อความเรียบง่าย:

 #[test] fn test_email_signature() { let headers = [ 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 115, 45, 97, 115, 99, 105, 105, 13, 10, 109, 105, 109, 101, 45, 118, 101, 114, 115, 105, 111, 110, 58, 49, 46, 48, 32, 40, 77, 97, 99, 32, 79, 83, 32, 88, 32, 77, 97, 105, 108, 32, 49, 54, 46, 48, 32, 92, 40, 51, 55, 51, 49, 46, 53, 48, 48, 46, 50, 51, 49, 92, 41, 41, 13, 10, 115, 117, 98, 106, 101, 99, 116, 58, 72, 101, 108, 108, 111, 13, 10, 109, 101, 115, 115, 97, 103, 101, 45, 105, 100, 58, 60, 56, 70, 56, 49, 57, 68, 51, 50, 45, 66, 54, 65, 67, 45, 52, 56, 57, 68, 45, 57, 55, 55, 70, 45, 52, 51, 56, 66, 66, 67, 52, 67, 65, 66, 50, 55, 64, 109, 101, 46, 99, 111, 109, 62, 13, 10, 100, 97, 116, 101, 58, 83, 97, 116, 44, 32, 50, 54, 32, 65, 117, 103, 32, 50, 48, 50, 51, 32, 49, 50, 58, 50, 53, 58, 50, 50, 32, 43, 48, 52, 48, 48, 13, 10, 116, 111, 58, 122, 107, 101, 119, 116, 101, 115, 116, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109, 13, 10, 100, 107, 105, 109, 45, 115, 105, 103, 110, 97, 116, 117, 114, 101, 58, 118, 61, 49, 59, 32, 97, 61, 114, 115, 97, 45, 115, 104, 97, 50, 53, 54, 59, 32, 99, 61, 114, 101, 108, 97, 120, 101, 100, 47, 114, 101, 108, 97, 120, 101, 100, 59, 32, 100, 61, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 59, 32, 115, 61, 49, 97, 49, 104, 97, 105, 59, 32, 116, 61, 49, 54, 57, 51, 48, 51, 56, 51, 51, 55, 59, 32, 98, 104, 61, 55, 120, 81, 77, 68, 117, 111, 86, 86, 85, 52, 109, 48, 87, 48, 87, 82, 86, 83, 114, 86, 88, 77, 101, 71, 83, 73, 65, 83, 115, 110, 117, 99, 75, 57, 100, 74, 115, 114, 99, 43, 118, 85, 61, 59, 32, 104, 61, 102, 114, 111, 109, 58, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 77, 105, 109, 101, 45, 86, 101, 114, 115, 105, 111, 110, 58, 83, 117, 98, 106, 101, 99, 116, 58, 77, 101, 115, 115, 97, 103, 101, 45, 73, 100, 58, 68, 97, 116, 101, 58, 116, 111, 59, 32, 98, 61 ]; let pubkey_limbs = [ 0xe5cf995b5ef59ce9943d1f4209b6ab, 0xe0caf03235e91a2db27e9ed214bcc6, 0xafe1309f87414bd36ed296dacfade2, 0xbeff3f19046a43adce46c932514988, 0x324041af8736e87de4358860fff057, 0xadcc6669dfa346f322717851a8c22a, 0x8b2a193089e6bf951c553b5a6f71aa, 0x0a570fe582918c4f731a0002068df2, 0x39419a433d6bfdd1978356cbca4b60, 0x550d695a514d38b45c862320a00ea5, 0x1c56ac1dfbf1beea31e8a613c2a51f, 0x6a30c9f22d2e5cb6934263d0838809, 0x0a281f268a44b21a4f77a91a52f960, 0x5134dc3966c8e91402669a47cc8597, 0x71590781df114ec072e641cdc5d224, 0xa1bc0f0937489c806c1944fd029dc9, 0x911f6e47f84db3b64c3648ebb5a127, 0xd5 ]; let pubkey_redc_limbs = [ 0xa48a824e4ebc7e0f1059f3ecfa57c4, 0x05c1db23f3c7d47ad7e7d7cfda5189, 0x79bb6bbbd8facf011f022fa9051aec, 0x24faa4cef474bed639362ea71f7a21, 0x1503aa50b77e24b030841a7d061581, 0x5bbf4e62805e1860a904c0f66a5fad, 0x5cbd24b72442d2ce647dd7d0a44368, 0x074a8839a4460c169dce7138efdaef, 0x0f06e09e3191b995b08e5b45182f65, 0x51fad4a89f8369fe10e5d4b6e149a1, 0xdc778b15982d11ebf7fe23b4e15f10, 0xa09ff3a4567077510c474e4ac0a21a, 0xb37e69e5dbb77167b73065e4c5ad6a, 0xecf4774e22e7fe3a38642186f7ae74, 0x16e72b5eb4c813a3b37998083aab81, 0xa48e7050aa8abedce5a45c16985376, 0xdd3285e53b322b221f7bcf4f8f8ad8, 0x0132 ]; let signature_limbs = [ 0x5779c85587e51cb8de5c29d7fdfeb0, 0xcd7ea8b6119f76f117ecb5042f8fc0, 0xeb7ac32b81d5a87bc2046fa0004e27, 0x62708c43b0c07a8fe8bdc97c479138, 0xc1e90d184f22a80be4a484a6ebd462, 0x39f3ff00e47728aaf74802d2d1d07b, 0x0f39de2cf99bf20dab7b8ae9240acd, 0xf4875cb76ce2538f255d70476136d6, 0xde151a5005ca614d6af7dd01e2a083, 0x6fe12b286f3195cae005fd7d2a1766, 0xd6e43a3060eccc555f2ee1e2929932, 0x0d5fa7cc79c794ae80310b491a1b40, 0x9cff415204cbc05c772ede05903440, 0xe7190ccff38575ae70dd055cd892d2, 0xf34bb777c0c842b0e88738eafdf634, 0x21040437e1e945a201ff58e542be68, 0x12f254fa4a0fb776ffe8759eb9eefa, 0x12 ]; let result = verify_email( headers, headers.len(), pubkey_limbs, pubkey_redc_limbs, signature_limbs ); assert(result, "email verification failed"); }


และรันการทดสอบ:

 nargo test
 [zkemail] Running 1 test function [zkemail] Testing test_email_signature... ok [zkemail] 1 test passed


นี่คือวิธีการตรวจสอบลายเซ็น DKIM ใน Noir แต่บัญชี zkEmail ไม่ได้มีแค่การตรวจสอบลายเซ็น DKIM เท่านั้น สุดท้ายแล้ว ใครๆ ก็สามารถส่งอีเมลและรับลายเซ็น DKIM ที่ถูกต้องได้


นอกจากนี้ เราต้องตรวจสอบว่าอีเมลถูกส่งจากที่อยู่อีเมลที่ถูกต้อง และอีเมลถูกส่งไปยังที่อยู่อีเมลที่ถูกต้อง รวมถึงตรวจสอบว่าหัวเรื่องอีเมลมีข้อมูลการโทรที่ถูกต้องหรือไม่ โปรดติดตามในตอนที่ 2 เร็วๆ นี้!


ระหว่างนี้ให้ชำระเงิน: