Skip to content

Commit d2bc9bb

Browse files
author
Will Bamberg
committed
Show Sign/Encrypt buttons only after Import
1 parent fdc66d0 commit d2bc9bb

File tree

6 files changed

+123
-50
lines changed

6 files changed

+123
-50
lines changed

web-crypto/import-key/index.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ <h1>Web Crypto: importKey</h1>
1818
<li>SubjectPublicKeyInfo</li>
1919
<li>JSON Web Key</li>
2020
</ul>
21-
<p>Each example has the same structure: you get a message and two buttons, one labeled "Import Key" and the other labeled either "Sign" or "Encrypt", depending on the type of key we are importing. The "Sign"/"Encrypt" button is disabled initially.</p>
21+
<p>Each example has the same structure: you get a message a button labeled "Import Key".</p>
2222
<p>If you click "Import Key" then the example imports a particular key:</p>
2323
<ul>
2424
<li>For "Raw", an AES encryption key.</li>
2525
<li>For "PKCS #8", an RSA private signing key.</li>
2626
<li>For "SubjectPublicKeyInfo", an RSA public encryption key.</li>
2727
<li>For "JSON Web Key", an EC private signing key.</li>
2828
</ul>
29-
<p>The "Sign"/"Encrypt" button is then enabled, and you can click it to use the imported key to perform the appropriate operation and display the result.</p>
29+
<p>A new button is then displayed, labeled "Sign" or "Encrypt", depending on the key that was imported. You can click it to use the imported key to perform the appropriate operation and display the result.</p>
3030
</section>
3131

3232
<section class="examples">
@@ -41,7 +41,7 @@ <h2 class="import-key-heading">Raw</h2>
4141
</div>
4242
<div class="ciphertext">Ciphertext:<span class="ciphertext-value"></span></div>
4343
<input class="import-key-button" type="button" value="Import Key">
44-
<input class="encrypt-button" type="button" value="Encrypt" disabled>
44+
<input class="encrypt-button hidden" type="button" value="Encrypt" disabled>
4545
</section>
4646
</section>
4747

@@ -55,7 +55,7 @@ <h2 class="import-key-heading">PKCS #8</h2>
5555
</div>
5656
<div class="signature">Signature:<span class="signature-value"></span></div>
5757
<input class="import-key-button" type="button" value="Import Key">
58-
<input class="sign-button" type="button" value="Sign" disabled>
58+
<input class="sign-button hidden" type="button" value="Sign" disabled>
5959
</section>
6060
</section>
6161

@@ -69,7 +69,7 @@ <h2 class="import-key-heading">SubjectPublicKeyInfo</h2>
6969
</div>
7070
<div class="ciphertext">Ciphertext:<span class="ciphertext-value"></span></div>
7171
<input class="import-key-button" type="button" value="Import Key">
72-
<input class="encrypt-button" type="button" value="Encrypt" disabled>
72+
<input class="encrypt-button hidden" type="button" value="Encrypt" disabled>
7373
</section>
7474
</section>
7575

@@ -83,7 +83,7 @@ <h2 class="import-key-heading">JSON Web Key</h2>
8383
</div>
8484
<div class="signature">Signature:<span class="signature-value"></span></div>
8585
<input class="import-key-button" type="button" value="Import Key">
86-
<input class="sign-button" type="button" value="Sign" disabled>
86+
<input class="sign-button hidden" type="button" value="Sign" disabled>
8787
</section>
8888
</section>
8989

web-crypto/import-key/jwk.js

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
"y": "hHUag3OvDzEr0uUQND4PXHQTXP5IDGdYhJhL-WLKjnGjQAw0rNGy5V29-aV-yseW"
1111
};
1212

13+
/*
14+
The unwrapped signing key.
15+
*/
16+
let signingKey;
17+
18+
const signButton = document.querySelector(".jwk .sign-button");
19+
1320
/*
1421
Import a JSON Web Key format EC private key, to use for ECDSA signing.
1522
Takes a string containing the JSON Web Key, and returns a Promise
@@ -43,14 +50,14 @@
4350
Get the encoded message-to-sign, sign it and display a representation
4451
of the first part of it in the "signature" element.
4552
*/
46-
async function signMessage(privateKey) {
53+
async function signMessage() {
4754
const encoded = getMessageEncoding();
4855
const signature = await window.crypto.subtle.sign(
4956
{
5057
name: "ECDSA",
5158
hash: "SHA-512"
5259
},
53-
privateKey,
60+
signingKey,
5461
encoded
5562
);
5663

@@ -63,20 +70,29 @@
6370
signatureValue.textContent = `${buffer}...[${signature.byteLength} bytes total]`;
6471
}
6572

73+
/*
74+
Show and enable the sign button.
75+
*/
76+
function enableSignButton() {
77+
signButton.classList.add('fade-in');
78+
signButton.addEventListener('animationend', () => {
79+
signButton.classList.remove('fade-in');
80+
});
81+
signButton.removeAttribute("disabled");
82+
signButton.classList.remove("hidden");
83+
}
84+
6685
/*
6786
When the user clicks "Import Key"
6887
- import the key
6988
- enable the "Sign" button
70-
- add a listener to "Sign" that uses the key.
7189
*/
7290
const importKeyButton = document.querySelector(".jwk .import-key-button");
7391
importKeyButton.addEventListener("click", async () => {
74-
const privateKey = await importPrivateKey(jwkEcKey);
75-
const signButton = document.querySelector(".jwk .sign-button");
76-
signButton.removeAttribute("disabled");
77-
signButton.addEventListener("click", () => {
78-
signMessage(privateKey);
79-
});
92+
signingKey = await importPrivateKey(jwkEcKey);
93+
enableSignButton();
8094
});
8195

96+
signButton.addEventListener("click", signMessage);
97+
8298
})();

web-crypto/import-key/pkcs8.js

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
(() => {
22

3+
const pemEncodedKey = `-----BEGIN PRIVATE KEY-----
4+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDD0tPV/du2vftjvXj1t/gXTK39sNBVrOAEb/jKzXae+Xa0H+3LhZaQIQNMfACiBSgIfZUvEGb+7TqXWQpoLoFR/R7MvGWcSk98JyrVtveD8ZmZYyItSY7m2hcasqAFiKyOouV5vzyRe87/lEyzzBpF3bQQ4IDaQu+K9Hj5fKuU6rrOeOhsdnJc+VdDQLScHxvMoLZ9Vtt+oK9J4/tOLwr4CG8khDlBURcBY6gPcLo3dPU09SW+6ctX2cX4mkXx6O/0mmdTmacr/vu50KdRMleFeZYOWPAEhhMfywybTuzBiPVIZVP8WFCSKNMbfi1S9A9PdBqnebwwHhX3/hsEBt2BAgMBAAECggEABEI1P6nf6Zs7mJlyBDv+Pfl5rjL2cOqLy6TovvZVblMkCPpJyFuNIPDK2tK2i897ZaXfhPDBIKmllM2Hq6jZQKB110OAnTPDg0JxzMiIHPs32S1d/KilHjGff4Hjd4NXp1l1Dp8BUPOllorR2TYm2x6dcCGFw9lhTr8O03Qp4hjn84VjGIWADYCk83mgS4nRsnHkdiqYnWx1AjKlY51yEK6RcrDMi0Th2RXrrINoC35sVv+APt2rkoMGi52RwTEseA1KZGFrxjq61ReJif6p2VXEcvHeX6CWLx014LGk43z6Q28P6HgeEVEfIjyqCUea5Du/mYb/QsRSCosXLxBqwQKBgQD1+fdC9ZiMrVI+km7Nx2CKBn8rJrDmUh5SbXn2MYJdrUd8bYNnZkCgKMgxVXsvJrbmVOrby2txOiqudZkk5mD3E5O/QZWPWQLgRu8ueYNpobAX9NRgNfZ7rZD+81vh5MfZiXfuZOuzv29iZhU0oqyZ9y75eHkLdrerNkwYOe5aUQKBgQDLzapDi1NxkBgsj9iiO4KUa7jvD4JjRqFy4Zhj/jbQvlvM0F/uFp7sxVcHGx4r11C+6iCbhX4u+Zuu0HGjT4d+hNXmgGyxR8fIUVxOlOtDkVJa5sOBZK73/9/MBeKusdmJPRhalZQfMUJRWIoEVDMhfg3tW/rBj5RYAtP2dTVUMQKBgDs8yr52dRmT+BWXoFWwaWB0NhYHSFz/c8v4D4Ip5DJ5M5kUqquxJWksySGQa40sbqnD05fBQovPLU48hfgr/zghn9hUjBcsoZOvoZR4sRw0UztBvA+7jzOz1hKAOyWIulR6Vca0yUrNlJ6G5R56+sRNkiOETupi2dLCzcqb0PoxAoGAZyNHvTLvIZN4iGSrjz5qkM4LIwBIThFadxbv1fq6pt0O/BGf2o+cEdq0diYlGK64cEVwBwSBnSg4vzlBqRIAUejLjwEDAJyA4EE8Y5A9l04dzV7nJb5cRak6CrgXxay/mBJRFtaHxVlaZGxYPGSYE6UFS0+3EOmmevvDZQBf4qECgYEA0ZF6Vavz28+8wLO6SP3w8NmpHk7K9tGEvUfQ30SgDx4G7qPIgfPrbB4OP/E0qCfsIImi3sCPpjvUMQdVVZyPOIMuB+rV3ZOxkrzxEUOrpOpR48FZbL7RN90yRQsAsrp9e4iv8QwB3VxLe7X0TDqqnRyqrc/osGzuS2ZcHOKmCU8=
5+
-----END PRIVATE KEY-----`;
6+
7+
/*
8+
The unwrapped signing key.
9+
*/
10+
let signingKey;
11+
12+
const signButton = document.querySelector(".pkcs8 .sign-button");
13+
314
/*
415
Convert a string into an ArrayBuffer
516
from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
@@ -13,10 +24,6 @@
1324
return buf;
1425
}
1526

16-
const pemEncodedKey = `-----BEGIN PRIVATE KEY-----
17-
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDD0tPV/du2vftjvXj1t/gXTK39sNBVrOAEb/jKzXae+Xa0H+3LhZaQIQNMfACiBSgIfZUvEGb+7TqXWQpoLoFR/R7MvGWcSk98JyrVtveD8ZmZYyItSY7m2hcasqAFiKyOouV5vzyRe87/lEyzzBpF3bQQ4IDaQu+K9Hj5fKuU6rrOeOhsdnJc+VdDQLScHxvMoLZ9Vtt+oK9J4/tOLwr4CG8khDlBURcBY6gPcLo3dPU09SW+6ctX2cX4mkXx6O/0mmdTmacr/vu50KdRMleFeZYOWPAEhhMfywybTuzBiPVIZVP8WFCSKNMbfi1S9A9PdBqnebwwHhX3/hsEBt2BAgMBAAECggEABEI1P6nf6Zs7mJlyBDv+Pfl5rjL2cOqLy6TovvZVblMkCPpJyFuNIPDK2tK2i897ZaXfhPDBIKmllM2Hq6jZQKB110OAnTPDg0JxzMiIHPs32S1d/KilHjGff4Hjd4NXp1l1Dp8BUPOllorR2TYm2x6dcCGFw9lhTr8O03Qp4hjn84VjGIWADYCk83mgS4nRsnHkdiqYnWx1AjKlY51yEK6RcrDMi0Th2RXrrINoC35sVv+APt2rkoMGi52RwTEseA1KZGFrxjq61ReJif6p2VXEcvHeX6CWLx014LGk43z6Q28P6HgeEVEfIjyqCUea5Du/mYb/QsRSCosXLxBqwQKBgQD1+fdC9ZiMrVI+km7Nx2CKBn8rJrDmUh5SbXn2MYJdrUd8bYNnZkCgKMgxVXsvJrbmVOrby2txOiqudZkk5mD3E5O/QZWPWQLgRu8ueYNpobAX9NRgNfZ7rZD+81vh5MfZiXfuZOuzv29iZhU0oqyZ9y75eHkLdrerNkwYOe5aUQKBgQDLzapDi1NxkBgsj9iiO4KUa7jvD4JjRqFy4Zhj/jbQvlvM0F/uFp7sxVcHGx4r11C+6iCbhX4u+Zuu0HGjT4d+hNXmgGyxR8fIUVxOlOtDkVJa5sOBZK73/9/MBeKusdmJPRhalZQfMUJRWIoEVDMhfg3tW/rBj5RYAtP2dTVUMQKBgDs8yr52dRmT+BWXoFWwaWB0NhYHSFz/c8v4D4Ip5DJ5M5kUqquxJWksySGQa40sbqnD05fBQovPLU48hfgr/zghn9hUjBcsoZOvoZR4sRw0UztBvA+7jzOz1hKAOyWIulR6Vca0yUrNlJ6G5R56+sRNkiOETupi2dLCzcqb0PoxAoGAZyNHvTLvIZN4iGSrjz5qkM4LIwBIThFadxbv1fq6pt0O/BGf2o+cEdq0diYlGK64cEVwBwSBnSg4vzlBqRIAUejLjwEDAJyA4EE8Y5A9l04dzV7nJb5cRak6CrgXxay/mBJRFtaHxVlaZGxYPGSYE6UFS0+3EOmmevvDZQBf4qECgYEA0ZF6Vavz28+8wLO6SP3w8NmpHk7K9tGEvUfQ30SgDx4G7qPIgfPrbB4OP/E0qCfsIImi3sCPpjvUMQdVVZyPOIMuB+rV3ZOxkrzxEUOrpOpR48FZbL7RN90yRQsAsrp9e4iv8QwB3VxLe7X0TDqqnRyqrc/osGzuS2ZcHOKmCU8=
18-
-----END PRIVATE KEY-----`;
19-
2027
/*
2128
Import a PEM encoded RSA private key, to use for RSA-PSS signing.
2229
Takes a string containing the PEM encoded key, and returns a Promise
@@ -62,14 +69,14 @@ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDD0tPV/du2vftjvXj1t/gXTK39sNBV
6269
Get the encoded message-to-sign, sign it and display a representation
6370
of the first part of it in the "signature" element.
6471
*/
65-
async function signMessage(privateKey) {
72+
async function signMessage() {
6673
const encoded = getMessageEncoding();
6774
const signature = await window.crypto.subtle.sign(
6875
{
6976
name: "RSA-PSS",
7077
saltLength: 32,
7178
},
72-
privateKey,
79+
signingKey,
7380
encoded
7481
);
7582

@@ -82,20 +89,29 @@ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDD0tPV/du2vftjvXj1t/gXTK39sNBV
8289
signatureValue.textContent = `${buffer}...[${signature.byteLength} bytes total]`;
8390
}
8491

92+
/*
93+
Show and enable the sign button.
94+
*/
95+
function enableSignButton() {
96+
signButton.classList.add('fade-in');
97+
signButton.addEventListener('animationend', () => {
98+
signButton.classList.remove('fade-in');
99+
});
100+
signButton.removeAttribute("disabled");
101+
signButton.classList.remove("hidden");
102+
}
103+
85104
/*
86105
When the user clicks "Import Key"
87106
- import the key
88107
- enable the "Sign" button
89-
- add a listener to "Sign" that uses the key.
90108
*/
91109
const importKeyButton = document.querySelector(".pkcs8 .import-key-button");
92110
importKeyButton.addEventListener("click", async () => {
93-
const privateKey = await importPrivateKey(pemEncodedKey);
94-
const signButton = document.querySelector(".pkcs8 .sign-button");
95-
signButton.removeAttribute("disabled");
96-
signButton.addEventListener("click", () => {
97-
signMessage(privateKey);
98-
});
111+
signingKey = await importPrivateKey(pemEncodedKey);
112+
enableSignButton();
99113
});
100114

115+
signButton.addEventListener("click", signMessage);
116+
101117
})();

web-crypto/import-key/raw.js

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
const rawKey = window.crypto.getRandomValues(new Uint8Array(16));
44

5+
/*
6+
The imported secret key.
7+
*/
8+
let secretKey;
9+
10+
const encryptButton = document.querySelector(".raw .encrypt-button");
11+
512
/*
613
Import an AES secret key from an ArrayBuffer containing the raw bytes.
714
Takes an ArrayBuffer string containing the bytes, and returns a Promise
@@ -32,7 +39,7 @@
3239
Get the encoded message, encrypt it and display a representation
3340
of the ciphertext in the "Ciphertext" element.
3441
*/
35-
async function encryptMessage(key) {
42+
async function encryptMessage() {
3643
const encoded = getMessageEncoding();
3744
// iv will be needed for decryption
3845
const iv = window.crypto.getRandomValues(new Uint8Array(12));
@@ -41,7 +48,7 @@
4148
name: "AES-GCM",
4249
iv: iv
4350
},
44-
key,
51+
secretKey,
4552
encoded
4653
);
4754

@@ -54,20 +61,29 @@
5461
ciphertextValue.textContent = `${buffer}...[${ciphertext.byteLength} bytes total]`;
5562
}
5663

64+
/*
65+
Show and enable the encrypt button.
66+
*/
67+
function enableEncryptButton() {
68+
encryptButton.classList.add('fade-in');
69+
encryptButton.addEventListener('animationend', () => {
70+
encryptButton.classList.remove('fade-in');
71+
});
72+
encryptButton.removeAttribute("disabled");
73+
encryptButton.classList.remove("hidden");
74+
}
75+
5776
/*
5877
When the user clicks "Import Key"
5978
- import the key
6079
- enable the "Encrypt" button
61-
- add a listener to "Encrypt" that uses the key.
6280
*/
6381
const importKeyButton = document.querySelector(".raw .import-key-button");
6482
importKeyButton.addEventListener("click", async () => {
65-
const secretKey = await importSecretKey(rawKey);
66-
const encryptButton = document.querySelector(".raw .encrypt-button");
67-
encryptButton.removeAttribute("disabled");
68-
encryptButton.addEventListener("click", () => {
69-
encryptMessage(secretKey);
70-
});
83+
secretKey = await importSecretKey(rawKey);
84+
enableEncryptButton();
7185
});
7286

87+
encryptButton.addEventListener("click", encryptMessage);
88+
7389
})();

web-crypto/import-key/spki.js

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
(() => {
22

3+
const pemEncodedKey = `-----BEGIN PUBLIC KEY-----
4+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy3Xo3U13dc+xojwQYWoJLCbOQ5fOVY8LlnqcJm1W1BFtxIhOAJWohiHuIRMctv7dzx47TLlmARSKvTRjd0dF92jx/xY20Lz+DXp8YL5yUWAFgA3XkO3LSJgEOex10NB8jfkmgSb7QIudTVvbbUDfd5fwIBmCtaCwWx7NyeWWDb7A9cFxj7EjRdrDaK3ux/ToMLHFXVLqSL341TkCf4ZQoz96RFPUGPPLOfvN0x66CM1PQCkdhzjE6U5XGE964ZkkYUPPsy6Dcie4obhW4vDjgUmLzv0z7UD010RLIneUgDE2FqBfY/C+uWigNPBPkkQ+Bv/UigS6dHqTCVeD5wgyBQIDAQAB
5+
-----END PUBLIC KEY-----`;
6+
7+
/*
8+
The unwrapped signing key.
9+
*/
10+
let encryptionKey;
11+
12+
const encryptButton = document.querySelector(".spki .encrypt-button");
13+
314
/*
415
Convert a string into an ArrayBuffer
516
from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
@@ -13,10 +24,6 @@
1324
return buf;
1425
}
1526

16-
const pemEncodedKey = `-----BEGIN PUBLIC KEY-----
17-
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy3Xo3U13dc+xojwQYWoJLCbOQ5fOVY8LlnqcJm1W1BFtxIhOAJWohiHuIRMctv7dzx47TLlmARSKvTRjd0dF92jx/xY20Lz+DXp8YL5yUWAFgA3XkO3LSJgEOex10NB8jfkmgSb7QIudTVvbbUDfd5fwIBmCtaCwWx7NyeWWDb7A9cFxj7EjRdrDaK3ux/ToMLHFXVLqSL341TkCf4ZQoz96RFPUGPPLOfvN0x66CM1PQCkdhzjE6U5XGE964ZkkYUPPsy6Dcie4obhW4vDjgUmLzv0z7UD010RLIneUgDE2FqBfY/C+uWigNPBPkkQ+Bv/UigS6dHqTCVeD5wgyBQIDAQAB
18-
-----END PUBLIC KEY-----`;
19-
2027
/*
2128
Import a PEM encoded RSA public key, to use for RSA-OAEP encryption.
2229
Takes a string containing the PEM encoded key, and returns a Promise
@@ -59,13 +66,13 @@ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy3Xo3U13dc+xojwQYWoJLCbOQ5fOVY8Llnqc
5966
Get the encoded message, encrypt it and display a representation
6067
of the ciphertext in the "Ciphertext" element.
6168
*/
62-
async function encryptMessage(key) {
69+
async function encryptMessage() {
6370
const encoded = getMessageEncoding();
6471
const ciphertext = await window.crypto.subtle.encrypt(
6572
{
6673
name: "RSA-OAEP"
6774
},
68-
key,
75+
encryptionKey,
6976
encoded
7077
);
7178

@@ -78,20 +85,29 @@ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy3Xo3U13dc+xojwQYWoJLCbOQ5fOVY8Llnqc
7885
ciphertextValue.textContent = `${buffer}...[${ciphertext.byteLength} bytes total]`;
7986
}
8087

88+
/*
89+
Show and enable the encrypt button.
90+
*/
91+
function enableEncryptButton() {
92+
encryptButton.classList.add('fade-in');
93+
encryptButton.addEventListener('animationend', () => {
94+
encryptButton.classList.remove('fade-in');
95+
});
96+
encryptButton.removeAttribute("disabled");
97+
encryptButton.classList.remove("hidden");
98+
}
99+
81100
/*
82101
When the user clicks "Import Key"
83102
- import the key
84103
- enable the "Encrypt" button
85-
- add a listener to "Encrypt" that uses the key.
86104
*/
87105
const importKeyButton = document.querySelector(".spki .import-key-button");
88106
importKeyButton.addEventListener("click", async () => {
89-
const publicKey = await importPublicKey(pemEncodedKey);
90-
const encryptButton = document.querySelector(".spki .encrypt-button");
91-
encryptButton.removeAttribute("disabled");
92-
encryptButton.addEventListener("click", () => {
93-
encryptMessage(publicKey);
94-
});
107+
encryptionKey = await importPublicKey(pemEncodedKey);
108+
enableEncryptButton();
95109
});
96110

111+
encryptButton.addEventListener("click", encryptMessage);
112+
97113
})();

web-crypto/import-key/style.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ h1 {
3939
font-family: monospace;
4040
}
4141

42+
.sign-button, .encrypt-button {
43+
background-color: green;
44+
color: white;
45+
}
46+
47+
.hidden {
48+
display: none;
49+
}
50+
4251
/* Whole page grid */
4352
main {
4453
display: grid;

0 commit comments

Comments
 (0)