សូមអរគុណយ៉ាងខ្លាំងដល់ក្រុម Mach34 សម្រាប់កំណែដំបូងនៃ zkemail នៅក្នុង Noir ។
គណនី zkEmail គឺជាគណនីកិច្ចសន្យាឆ្លាតវៃដែលអនុញ្ញាតឱ្យអ្នកប្រើប្រាស់បញ្ជាក់ប្រតិបត្តិការដោយឆ្លើយតបទៅអ៊ីមែល។ តើវាដំណើរការយ៉ាងដូចម្តេច? សារអ៊ីមែលនីមួយៗត្រូវបានចុះហត្ថលេខាដោយអ្នកផ្តល់អ៊ីមែលរបស់អ្នកប្រើ (ឧ. iCloud, Gmail ឬ ProtonMail) ។ គណនីកិច្ចសន្យាឆ្លាតវៃរបស់អ្នកប្រើប្រាស់ផ្ទៀងផ្ទាត់ហត្ថលេខានៅលើខ្សែសង្វាក់ ហើយប្រតិបត្តិប្រតិបត្តិការប្រសិនបើហត្ថលេខាមានសុពលភាព។ បន្ថែមពីលើការផ្ទៀងផ្ទាត់ហត្ថលេខា វាក៏សំខាន់ផងដែរក្នុងការផ្ទៀងផ្ទាត់នោះ។
Alice ផ្ញើអ៊ីមែលខាងក្រោមទៅកាន់អ្នកបញ្ជូនបន្ត៖
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 ។ អត្ថបទដែលនៅសល់នឹងពន្យល់៖
ហត្ថលេខា DKIM ត្រូវបានបង្កើតឡើងដោយអ្នកផ្តល់អ៊ីមែលដែលចុះហត្ថលេខាលើសំណុំរងនៃបឋមកថាក្នុងលំដាប់ត្រឹមត្រូវ និងទម្រង់ Canonical ។ តោះមើលបឋមកថា DKIM-Signature៖
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
។ សូមក្រឡេកមើលបឋមកថាមុនពេល canonicalization៖
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]
ហើយបន្ទាប់ពី canonicalization:
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
ក៏ត្រូវបានបញ្ចូលទៅក្នុងបឋមកថា canonicalized ប៉ុន្តែវាបាត់តម្លៃនៃប៉ារ៉ាម៉ែត្រ b=
។ មានតែកូនសោប៉ុណ្ណោះដែលត្រូវបានរួមបញ្ចូល។
នៅពេលផ្ញើអ៊ីមែល iCloud.com នឹងចុះហត្ថលេខាលើបឋមកថា Canonicalized ដោយប្រើសោឯកជនរបស់វា។ បន្ទាប់មកហត្ថលេខាត្រូវបានបញ្ចូលក្នុងបឋមកថា DKIM-Signature
។ ជាក់លាក់នៅក្នុងប៉ារ៉ាម៉ែត្រ b=
។
2 សំណួរ៖
ប្រសិនបើអ្នកក្រឡេកមើលបឋមកថា DKIM-Signature
ពីខាងលើ អ្នកនឹងសម្គាល់ឃើញ 2 ប៉ារ៉ាម៉ែត្រ៖ d=icloud.com
និង s=1a1hai
។ ទាំងនេះគឺជា d
omain និង 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
: បឋមកថា canonicalized ជាអារេនៃបៃ។ វាមានប្រវែងថេរ ហើយត្រូវមានទ្រនាប់ជាមួយ 0 នៅខាងចុងheaders_len
: ប្រវែងពិតប្រាកដនៃបឋមកថាpubkey_limbs
& pubkey_redc_limbs
: សោសាធារណៈរបស់អ្នកផ្តល់អ៊ីមែលដែលបានអ៊ិនកូដជាពិសេសសម្រាប់ Noirsignature
៖ ហត្ថលេខារបស់អ្នកផ្តល់អ៊ីមែលដែលបានអ៊ិនកូដជាពិសេសសម្រាប់ Noir
នៅក្នុងតួមុខងារ ដំបូងយើងបំប្លែងហត្ថលេខា និងសោសាធារណៈទៅជាលេខធំ។ បន្ទាប់មកយើងដកបឋមកថា canonicalized ជាមួយ sha256 ហើយផ្ទៀងផ្ទាត់ហត្ថលេខាដោយប្រើ public key និង hash។
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 តើយើងត្រូវបំប្លែងខ្សែអ៊ីមែលឆៅទៅជាធាតុបញ្ចូលដែលមានរចនាសម្ព័ន្ធសម្រាប់សៀគ្វីដោយរបៀបណា?
ចូរចាប់ផ្តើមជាមួយនឹងបឋមកថា។ ខ្ញុំនឹងប្រើ 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 លេខធំ។ មានតែ បណ្ណាល័យ 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 ដែលមានសុពលភាព។
យើងក៏ត្រូវផ្ទៀងផ្ទាត់ថាអ៊ីមែលត្រូវបានផ្ញើចេញពីអាសយដ្ឋានត្រឹមត្រូវ ហើយអ៊ីមែលត្រូវបានផ្ញើទៅអាសយដ្ឋានត្រឹមត្រូវ។ ក៏ដូចជាប្រធានបទអ៊ីមែលមានទិន្នន័យហៅទូរសព្ទត្រឹមត្រូវ។ រង់ចាំតាមដាន ភាគ២ ឆាប់ៗនេះ!
ទន្ទឹមនឹងនេះ ពិនិត្យចេញ៖