Skip to content

Commit

Permalink
Switch to the Web Crypto API for generating SHA checksums
Browse files Browse the repository at this point in the history
This allows us to drop the two pure JavaScript implementations of SHA-1
and SHA-256. These native Web Crypto API is available as baseline and allows us to
easily switch over to SHA-512 without adding a new dependency.
  • Loading branch information
jelly authored and martinpitt committed Jan 16, 2025
1 parent d9b5815 commit b6c323c
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 12 deletions.
2 changes: 1 addition & 1 deletion node_modules
Submodule node_modules updated 1242 files
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
"@patternfly/react-table": "5.4.13",
"@patternfly/react-tokens": "5.4.1",
"dequal": "2.0.3",
"js-sha1": "0.7.0",
"js-sha256": "0.11.0",
"json-stable-stringify-without-jsonify": "1.0.1",
"prop-types": "15.8.1",
"react": "18.3.1",
Expand Down
44 changes: 36 additions & 8 deletions pkg/storaged/crypto/tang.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ import React from "react";
import { ClipboardCopy } from "@patternfly/react-core/dist/esm/components/ClipboardCopy/index.js";
import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/esm/components/Text/index.js";

import sha1 from "js-sha1";
import sha256 from "js-sha256";
import { useInit } from "hooks";

import stable_stringify from "json-stable-stringify-without-jsonify";

const _ = cockpit.gettext;

async function digest(text, hash) {
const encoder = new TextEncoder();
const data = encoder.encode(text);
const digest = await window.crypto.subtle.digest(hash, data);
return [...new Uint8Array(digest)];
}

export function validate_url(url) {
if (url.length === 0)
return _("Address cannot be empty");
Expand Down Expand Up @@ -68,7 +75,7 @@ function jwk_b64_encode(bytes) {
.replace(/=+$/, '');
}

function compute_thp(jwk) {
async function compute_thp(jwk) {
const REQUIRED_ATTRS = {
RSA: ['kty', 'p', 'd', 'q', 'dp', 'dq', 'qi', 'oth'],
EC: ['kty', 'crv', 'x', 'y'],
Expand All @@ -83,10 +90,23 @@ function compute_thp(jwk) {
const req = REQUIRED_ATTRS[jwk.kty];
const norm = { };
req.forEach(k => { if (k in jwk) norm[k] = jwk[k]; });
return {
sha256: jwk_b64_encode(sha256.digest(stable_stringify(norm))),
sha1: jwk_b64_encode(sha1.digest(stable_stringify(norm)))
};

const hashes = {};
try {
const sha256 = jwk_b64_encode(await digest(stable_stringify(norm), "SHA-256"));
hashes.sha256 = sha256;
} catch (err) {
console.warn("Unable to create a sha256 hash", err);
}

try {
const sha1 = jwk_b64_encode(await digest(stable_stringify(norm), "SHA-1"));
hashes.sha1 = sha1;
} catch (err) {
console.warn("Unable to create a sha1 hash", err);
}

return hashes;
}

function compute_sigkey_thps(adv) {
Expand All @@ -106,7 +126,15 @@ function compute_sigkey_thps(adv) {
export const TangKeyVerification = ({ url, adv }) => {
const parsed = parse_url(url);
const cmd = cockpit.format("ssh $0 tang-show-keys $1", parsed.hostname, parsed.port);
const sigkey_thps = compute_sigkey_thps(tang_adv_payload(adv));
const [sigkey_thps, setSigKey] = React.useState(null);

useInit(async () => {
const sigkey = await Promise.all(compute_sigkey_thps(tang_adv_payload(adv)));
setSigKey(sigkey);
});

if (sigkey_thps === null)
return null;

return (
<TextContent>
Expand Down
1 change: 0 additions & 1 deletion tools/build-debian-copyright
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ license_patterns = {
copyright_patterns = {
# Common patterns
r'Copyright (.*)$': [r'\1'],
r'@copyright (.*)$': [r'\1'],
r'\(c\) (.*)$': [r'\1'],

# https://github.com/focus-trap/focus-trap/blob/master/LICENSE
Expand Down

0 comments on commit b6c323c

Please sign in to comment.