diff --git a/packages/web/package.json b/packages/web/package.json index 0cdfc9c17..b62af5a4a 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -15,6 +15,7 @@ "@hookform/resolvers": "^2.9.10", "@mui/icons-material": "^5.11.0", "@mui/material": "^5.11.4", + "@openpgp/web-stream-tools": "^0.0.14", "@trivago/prettier-plugin-sort-imports": "^4.1.1", "@types/dompurify": "^3.0.1", "@types/downloadjs": "^1.4.2", diff --git a/packages/web/src/pages/Submissions/SubmissionFormPage/encrypt.ts b/packages/web/src/pages/Submissions/SubmissionFormPage/encrypt.ts index c98fb8836..6b09b17d9 100644 --- a/packages/web/src/pages/Submissions/SubmissionFormPage/encrypt.ts +++ b/packages/web/src/pages/Submissions/SubmissionFormPage/encrypt.ts @@ -1,5 +1,6 @@ import { Key, MaybeArray, createMessage, encrypt, generateSessionKey, readKey } from "openpgp"; import { getHatsPublicKey } from "./submissionsService.api"; +import { readToEnd } from "@openpgp/web-stream-tools"; const IpfsHash = require("ipfs-only-hash"); @@ -39,6 +40,48 @@ export async function encryptWithKeys(publicKeyOrKeys: string | string[], dataTo return { encryptedData, sessionKey }; } +export async function encryptFileWithKeys(publicKeyOrKeys: string | string[], fileToEncrypt: File) { + let encryptionKeys: MaybeArray; + + if (Array.isArray(publicKeyOrKeys)) { + encryptionKeys = []; + + const encryptionKeysList = await Promise.all(publicKeyOrKeys.map((key) => readKey({ armoredKey: key }))); + for (let key of encryptionKeysList) { + try { + await key.verifyPrimaryKey(); + encryptionKeys.push(key); + } catch { + continue; + } + } + + if (encryptionKeys.length === 0) return undefined; + } else { + encryptionKeys = await readKey({ armoredKey: publicKeyOrKeys }); + + try { + await encryptionKeys.verifyPrimaryKey(); + } catch (error) { + return undefined; + } + } + + const sessionKey = await generateSessionKey({ encryptionKeys }); + + const message = await encrypt({ + message: await createMessage({ binary: new Uint8Array(await fileToEncrypt.arrayBuffer() as ArrayBuffer) }), + encryptionKeys, + sessionKey, + }); + + const encryptedData = await readToEnd(message); + + const encryptedFile = new File([encryptedData], fileToEncrypt.name, {type: fileToEncrypt.type}) + + return { encryptedFile, sessionKey }; +} + export async function encryptWithHatsKey(dataToEncrypt: string): Promise { try { const hatsPublicKeyString = await getHatsPublicKey(); diff --git a/yarn.lock b/yarn.lock index 661da6801..3546cb2f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2522,6 +2522,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@openpgp/web-stream-tools@^0.0.14": + version "0.0.14" + resolved "https://registry.yarnpkg.com/@openpgp/web-stream-tools/-/web-stream-tools-0.0.14.tgz#513214cd2a20903558448980085155752be445e4" + integrity sha512-6btCNVf6YSsmlyIS7yw+IbzXeXCEcJxeSpxvSxkDuZj9B/ekt4fXkZj4oOaIxG4SKTftIK1svnlVroJ1cCMT4g== + "@pedrouid/environment@^1.0.1": version "1.0.1" resolved "https://registry.npmjs.org/@pedrouid/environment/-/environment-1.0.1.tgz"