Skip to content

Commit

Permalink
Add Ed25519 sign-verify example (#247)
Browse files Browse the repository at this point in the history
* Add Ed25519 sign-verify example

* Create ed25519.js

* Link to Chromium and Chrome command-line switch to enable the feature

* Close </a>

* Apply suggestions from code review

Co-authored-by: Daniel Huigens <d.huigens@protonmail.com>

* docs(web-crypto): add link to browser compat for ed25519, formatting

* Update web-crypto/sign-verify/index.html

Co-authored-by: Daniel Huigens <d.huigens@protonmail.com>

---------

Co-authored-by: Brian Thomas Smith <brian@smith.berlin>
Co-authored-by: Daniel Huigens <d.huigens@protonmail.com>
  • Loading branch information
3 people committed Feb 27, 2024
1 parent d529271 commit 9189afb
Show file tree
Hide file tree
Showing 3 changed files with 254 additions and 76 deletions.
74 changes: 74 additions & 0 deletions web-crypto/sign-verify/ed25519.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
(() => {
/*
Store the calculated signature here, so we can verify it later.
*/
let signature;

/*
Fetch the contents of the "message" textbox, and encode it
in a form we can use for sign operation.
*/
function getMessageEncoding() {
const messageBox = document.querySelector("#ed25519-message");
let message = messageBox.value;
let enc = new TextEncoder();
return enc.encode(message);
}

/*
Get the encoded message-to-sign, sign it and display a representation
of the first part of it in the "signature" element.
*/
async function signMessage(privateKey) {
const signatureValue = document.querySelector(".ed25519 .signature-value");
signatureValue.classList.remove("valid", "invalid");

let encoded = getMessageEncoding();
signature = await window.crypto.subtle.sign("Ed25519", privateKey, encoded);

signatureValue.classList.add("fade-in");
signatureValue.addEventListener("animationend", () => {
signatureValue.classList.remove("fade-in");
});
let buffer = new Uint8Array(signature, 0, 5);
signatureValue.textContent = `${buffer}...[${signature.byteLength} bytes total]`;
}

/*
Fetch the encoded message-to-sign and verify it against the stored signature.
* If it checks out, set the "valid" class on the signature.
* Otherwise set the "invalid" class.
*/
async function verifyMessage(publicKey) {
const signatureValue = document.querySelector(".ed25519 .signature-value");
signatureValue.classList.remove("valid", "invalid");

let encoded = getMessageEncoding();
let result = await window.crypto.subtle.verify(
"Ed25519",
publicKey,
signature,
encoded
);

signatureValue.classList.add(result ? "valid" : "invalid");
}

/*
Generate a sign/verify key, then set up event listeners
on the "Sign" and "Verify" buttons.
*/
window.crypto.subtle
.generateKey("Ed25519", true, ["sign", "verify"])
.then((keyPair) => {
const signButton = document.querySelector(".ed25519 .sign-button");
signButton.addEventListener("click", () => {
signMessage(keyPair.privateKey);
});

const verifyButton = document.querySelector(".ed25519 .verify-button");
verifyButton.addEventListener("click", () => {
verifyMessage(keyPair.publicKey);
});
});
})();
149 changes: 120 additions & 29 deletions web-crypto/sign-verify/index.html
Original file line number Diff line number Diff line change
@@ -1,30 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta charset="utf-8" />
<title>Web Crypto API example</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="style.css" />
</head>

<body>
<main>
<h1>Web Crypto: sign/verify</h1>

<section class="description">
<p>This page shows the use of the <code>sign()</code> and <code>verify()</code> functions of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API">Web Crypto API</a>. It contains four separate examples, one for each signing algorithm supported:</p>
<ul>
<p>
This page shows how to use the <code>sign()</code> and
<code>verify()</code> functions of the
<a
href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API"
>Web Crypto API</a
>. It contains examples for the following signing algorithms:
</p>
<ol>
<li>"RSASSA-PKCS1-v1_5"</li>
<li>"RSA-PSS"</li>
<li>"ECDSA"</li>
<li>"HMAC"</li>
</ul>
<hr/>
<li>
"Ed25519"
<ul>
<li class="caution-list-item">
<span class="caution">Caution: </span>For information about
Ed25519 support, see
<a
href="https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto#browser_compatibility"
>SubtleCrypto: Browser compatibility</a
>
and
<a
href="https://blogs.igalia.com/jfernandez/2023/06/20/secure-curves-in-the-web-cryptography-api/"
>Secure Curves in the Web Cryptography API</a
>. Chrome requires the
<code>enable-experimental-web-platform-features</code>
preference to be set via
<a
href="https://peter.sh/experiments/chromium-command-line-switches/#enable-experimental-web-platform-features"
>command-line switch</a
>
or via
<code
>chrome://flags/#enable-experimental-web-platform-features</code
>.
</li>
</ul>
</li>
</ol>
<hr />
<p>Each example has four components:</p>
<ul>
<li>A text box containing a message to sign.</li>
<li>A representation of the signature.</li>
<li>A "Sign" button: this signs the text box contents, displays part of the signature, and stores the complete signature.</li>
<li>A "Verify" button: this verifies the text box contents against the stored signature, and styles the displayed signature according to the result.</li>
<li>
A "Sign" button: this signs the text box contents, displays part of
the signature, and stores the complete signature.
</li>
<li>
A "Verify" button: this verifies the text box contents against the
stored signature, and styles the displayed signature according to
the result.
</li>
</ul>
<p>Try it:</p>
<ul>
Expand All @@ -41,12 +83,19 @@ <h2 class="sign-verify-heading">RSASSA-PKCS1-v1_5</h2>
<section class="sign-verify-controls">
<div class="message-control">
<label for="rsassa-pkcs1-message">Enter a message to sign:</label>
<input type="text" id="rsassa-pkcs1-message" name="message" size="25"
value="The owl hoots at midnight">
<input
type="text"
id="rsassa-pkcs1-message"
name="message"
size="25"
value="The owl hoots at midnight"
/>
</div>
<div class="signature">Signature:<span class="signature-value"></span></div>
<input class="sign-button" type="button" value="Sign">
<input class="verify-button" type="button" value="Verify">
<div class="signature">
Signature:<span class="signature-value"></span>
</div>
<input class="sign-button" type="button" value="Sign" />
<input class="verify-button" type="button" value="Verify" />
</section>
</section>

Expand All @@ -55,12 +104,19 @@ <h2 class="sign-verify-heading">RSA-PSS</h2>
<section class="sign-verify-controls">
<div class="message-control">
<label for="rsa-pss-message">Enter a message to sign:</label>
<input type="text" id="rsa-pss-message" name="message" size="25"
value="The tiger prowls at dawn">
<input
type="text"
id="rsa-pss-message"
name="message"
size="25"
value="The tiger prowls at dawn"
/>
</div>
<div class="signature">
Signature:<span class="signature-value"></span>
</div>
<div class="signature">Signature:<span class="signature-value"></span></div>
<input class="sign-button" type="button" value="Sign">
<input class="verify-button" type="button" value="Verify">
<input class="sign-button" type="button" value="Sign" />
<input class="verify-button" type="button" value="Verify" />
</section>
</section>

Expand All @@ -69,12 +125,19 @@ <h2 class="sign-verify-heading">ECDSA</h2>
<section class="sign-verify-controls">
<div class="message-control">
<label for="ecdsa-message">Enter a message to sign:</label>
<input type="text" id="ecdsa-message" name="message" size="25"
value="The eagle flies at twilight">
<input
type="text"
id="ecdsa-message"
name="message"
size="25"
value="The eagle flies at twilight"
/>
</div>
<div class="signature">Signature:<span class="signature-value"></span></div>
<input class="sign-button" type="button" value="Sign">
<input class="verify-button" type="button" value="Verify">
<div class="signature">
Signature:<span class="signature-value"></span>
</div>
<input class="sign-button" type="button" value="Sign" />
<input class="verify-button" type="button" value="Verify" />
</section>
</section>

Expand All @@ -83,20 +146,48 @@ <h2 class="sign-verify-heading">HMAC</h2>
<section class="sign-verify-controls">
<div class="message-control">
<label for="hmac-message">Enter a message to sign:</label>
<input type="text" id="hmac-message" name="message" size="25"
value="The bunny hops at teatime">
<input
type="text"
id="hmac-message"
name="message"
size="25"
value="The bunny hops at teatime"
/>
</div>
<div class="signature">
Signature:<span class="signature-value"></span>
</div>
<input class="sign-button" type="button" value="Sign" />
<input class="verify-button" type="button" value="Verify" />
</section>
</section>

<section class="sign-verify ed25519">
<h2 class="sign-verify-heading">Ed25519</h2>
<section class="sign-verify-controls">
<div class="message-control">
<label for="ed25519-message">Enter a message to sign:</label>
<input
type="text"
id="ed25519-message"
name="message"
size="25"
value="The lion roars near dawn"
/>
</div>
<div class="signature">
Signature:<span class="signature-value"></span>
</div>
<div class="signature">Signature:<span class="signature-value"></span></div>
<input class="sign-button" type="button" value="Sign">
<input class="verify-button" type="button" value="Verify">
<input class="sign-button" type="button" value="Sign" />
<input class="verify-button" type="button" value="Verify" />
</section>
</section>
</section>
</main>

</body>
<script src="rsassa-pkcs1.js"></script>
<script src="rsa-pss.js"></script>
<script src="ecdsa.js"></script>
<script src="hmac.js"></script>
<script src="ed25519.js"></script>
</html>

0 comments on commit 9189afb

Please sign in to comment.