paint-brush
zkEmail-Konto in Noir & Aztec – Teil 1von@oleh
Neue Geschichte

zkEmail-Konto in Noir & Aztec – Teil 1

von Oleh Misarosh11m2024/09/13
Read on Terminal Reader

Zu lang; Lesen

Ein zkEmail-Konto ist ein Smart-Contract-Konto, das es Benutzern ermöglicht, Transaktionen durch die Beantwortung einer E-Mail zu bestätigen.
featured image - zkEmail-Konto in Noir & Aztec – Teil 1
Oleh Misarosh HackerNoon profile picture
0-item
1-item

Großer Dank geht an das Mach34-Team für die erste Version von zkemail in Noir .

Einführung

Ein zkEmail-Konto ist ein Smart-Contract-Konto, mit dem Benutzer Transaktionen bestätigen können, indem sie auf eine E-Mail antworten. Wie funktioniert es? Jede E-Mail-Nachricht wird vom E-Mail-Anbieter des Benutzers (z. B. iCloud, Gmail oder ProtonMail) signiert. Das Smart-Contract-Konto des Benutzers überprüft die Signatur in der Kette und führt die Transaktion aus, wenn die Signatur gültig ist. Neben der Signaturüberprüfung ist es auch wichtig zu überprüfen, dass


  1. Die E-Mail wurde von der E-Mail-Adresse des Benutzers gesendet.
  2. Es wurde an die Relayer-E-Mail-Adresse gesendet und
  3. dass die E-Mail den richtigen Betreff enthält (der die Anrufdaten oder die TX-Beschreibung enthält).

Beispiel

Alice sendet die folgende E-Mail an einen Relayer:

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

Ist Ihnen der DKIM-Signature Header aufgefallen? Es handelt sich um die Signatur, die vom privaten Schlüssel von iCloud erstellt wurde. Im Rest des Artikels erfahren Sie mehr:


  1. Was genau wird von einem E-Mail-Anbieter signiert
  2. So erhalten Sie den öffentlichen Schlüssel Ihres E-Mail-Anbieters
  3. So überprüfen Sie die Signatur in Noir

Unterschrift

Eine DKIM-Signatur wird von einem E-Mail-Anbieter erstellt, der eine Teilmenge von Headern in der richtigen Reihenfolge und im kanonischen Format signiert. Werfen wir einen Blick auf einen DKIM-Signatur-Header:

 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==

Es besteht aus Schlüssel-Wert-Paaren, die durch Semikolon getrennt sind. Die wichtigen Teile sind: a= und b= . Lassen Sie es uns aufschlüsseln:


  • a= ist der zum Signieren der Nachricht verwendete Algorithmus. In diesem Fall ist es rsa-sha256 .
  • b= ist die Signatur selbst in Base64-Kodierung.

Was wird genau unterschrieben?

Die E-Mail-Header werden vor der Signierung sortiert und kanonisiert. Die Reihenfolge der Header wird durch den h= -Parameter des DKIM-Signature Headers angegeben. Anschließend werden die Header in Kleinbuchstaben umgewandelt, zusätzliche Leerzeichen werden entfernt und dann durch \r\n -Zeichen verbunden. Werfen wir einen Blick auf die Header vor der Kanonisierung:


 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]


Und nach der Kanonisierung:

 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=


Beachten Sie, dass der DKIM-Signature Header auch in den kanonisierten Headern enthalten ist, ihm jedoch der Wert des Parameters b= fehlt. Nur der Schlüssel ist enthalten.


Beim Senden einer E-Mail signiert iCloud.com die kanonisierten Header mit seinem privaten Schlüssel. Die Signatur wird dann in den DKIM-Signature Header aufgenommen. Genauer gesagt in den Parameter b= .

Öffentlicher Schlüssel des E-Mail-Anbieters

2 Fragen:

  1. Wie erhalte ich den öffentlichen Schlüssel des E-Mail-Anbieters?
  2. Wie verifiziere ich die Signatur in Noir?


Wenn Sie sich den DKIM-Signature Header von oben ansehen, werden Sie zwei Parameter bemerken: d=icloud.com und s=1a1hai . Dies sind die d und der s Empfänger des E-Mail-Anbieters. Wir können den öffentlichen Schlüssel erhalten, indem wir den spezifischen DNS-Eintrag abfragen: {s}._domainkey.{d} . In diesem Fall müssen wir 1a1hai._domainkey.icloud.com abfragen. Lassen Sie uns dies mit dem Befehl dig abfragen:

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


Wir erhalten folgende Antwort:

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


Der interessante Teil ist der Parameter p= . Bitte beachten Sie, dass er in mehrere Anführungszeichenzeilen aufgeteilt ist, sodass wir sie aneinanderreihen müssen. Das Ergebnis ist:

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


Dies ist der in Base64 kodierte öffentliche Schlüssel des E-Mail-Anbieters ( iCloud.com ). Wir werden ihn später verwenden, um eine Signatur in Noir zu verifizieren.

Noir-Rennstrecke

Aufgrund der Einschränkungen von ZK-Schaltungen müssen wir eine speziell optimierte Implementierung von RSA und großen Zahlen verwenden, die vom Noir-Team bereitgestellt wird: https://github.com/noir-lang/noir_rsa .


Installieren Sie es in Nargo.toml:

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


Schauen wir uns nun zur Verifizierung die Noir-Schaltung an:

 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) }


Der Kürze halber werde ich die Importe und Typdefinitionen überspringen (wen interessiert das schon, einfach kopieren und einfügen). Werfen wir einen Blick auf die Parameter verify_email :

  • headers : die kanonisierten Header als Byte-Array. Es hat eine feste Länge und muss am Ende mit 0 aufgefüllt werden
  • headers_len : die tatsächliche Länge der Header
  • pubkey_limbs & pubkey_redc_limbs : der öffentliche Schlüssel des E-Mail-Anbieters, speziell für Noir kodiert
  • signature : die speziell für Noir kodierte Signatur des E-Mail-Anbieters


Im Funktionskörper konvertieren wir zunächst die Signatur und den öffentlichen Schlüssel in eine große Anzahl von Instanzen. Dann hashen wir die kanonisierten Header mit sha256 und verifizieren die Signatur mit dem öffentlichen Schlüssel und dem 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)


Wenn die Überprüfung erfolgreich ist, gibt die Funktion true zurück, andernfalls false .

Von der Roh-E-Mail-Zeichenfolge bis zu Noir-Eingaben

Da wir nun über den Noir-Schaltkreis verfügen, stellt sich die Frage, wie wir eine Roh-E-Mail-Zeichenfolge in die strukturierten Eingaben für den Schaltkreis konvertieren?


Beginnen wir mit den Headern. Ich werde mailparser zum Parsen der E-Mails und dkim zum Extrahieren der kanonisierten Header verwenden. Parsen der E-Mail:

 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 }; }


Testen Sie es jetzt:

 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));


Wir erhalten die folgende Ausgabe:

 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="


Und konvertieren Sie es in Bytes:

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


Ausgabe:

 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 ]


Speichern Sie diese Ausgabe für später.


Konvertieren wir nun den öffentlichen Schlüssel und die Signatur des E-Mail-Anbieters in Noir Big Number Limbs. Es ist nur diese offizielle Rust-Bibliothek verfügbar. Aber Sie haben Glück, denn ich habe sie in wasm kompiliert und in npm veröffentlicht. Installieren wir sie:

 npm i @shieldswap/email_account_utils_rs


Es akzeptiert den öffentlichen Schlüssel und die Signatur in Base64 und gibt die Teile des öffentlichen Schlüssels und der Signatur im JSON-Format zurück:

 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(",") + "]");


Jetzt haben wir alle erforderlichen Daten, um die Signatur zu verifizieren. Also legen wir los. Der Einfachheit halber werde ich die von JavaScript generierten Daten in einen Noir-Test kopieren und einfügen:

 #[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"); }


Und führen Sie den Test aus:

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


So verifizieren Sie eine DKIM-Signatur in Noir. Aber ein zkEmail-Konto kann mehr als nur DKIM-Signaturen verifizieren. Letztlich kann jeder eine E-Mail senden und eine gültige DKIM-Signatur erhalten.


Wir müssen außerdem überprüfen, ob die E-Mail von der richtigen Adresse gesendet wurde und ob sie an die richtige Adresse gesendet wurde. Außerdem muss der Betreff der E-Mail die richtigen Anrufdaten enthalten. Bleiben Sie dran, Teil 2 folgt in Kürze!


Schauen Sie sich in der Zwischenzeit Folgendes an: