From d3dbdee9d1fac35f7ab0ac1ad500ff072ce283b2 Mon Sep 17 00:00:00 2001 From: Antariksh Date: Wed, 16 Jun 2021 17:22:58 +0800 Subject: [PATCH 1/5] docs: specify version for attachment functionality --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f9c206d..bcdf450 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,8 @@ app.post( express.json(), // Decrypt the submission and attachments async function (req, res, next) { - const submission = formsg.crypto.decryptWithAttachments( + // Note that this function is only available from version 0.9.0 onwards + const submission = await formsg.crypto.decryptWithAttachments( formSecretKey, // If `verifiedContent` is provided in `req.body.data`, the return object // will include a verified key. @@ -190,7 +191,7 @@ If the decrypted content is the correct shape, then: ### Processing Attachments -`formsg.crypto.decryptWithAttachments(formSecretKey: string, decryptParams: DecryptParams)` behaves similarly except it will return a `Promise`. +`formsg.crypto.decryptWithAttachments(formSecretKey: string, decryptParams: DecryptParams)` (available from version 0.9.0 onwards) behaves similarly except it will return a `Promise`. `DecryptedContentAndAttachments` is an object containing two fields: - `content`: the standard form decrypted responses (same as the return type of `formsg.crypto.decrypt`) From 3c49a9c3e1c1e88752862e5f94e90109be517fe3 Mon Sep 17 00:00:00 2001 From: Antariksh Date: Wed, 16 Jun 2021 19:05:15 +0800 Subject: [PATCH 2/5] docs: collapse code examples into one --- README.md | 47 ++++++++--------------------------------------- 1 file changed, 8 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index bcdf450..cdaa3ca 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,8 @@ app.post( // Parse JSON from raw request body express.json(), // Decrypt the submission - function (req, res, next) { + async function (req, res, next) { + // Use `decrypt` if the submission does not contain attachments const submission = formsg.crypto.decrypt( formSecretKey, // If `verifiedContent` is provided in `req.body.data`, the return object @@ -70,46 +71,14 @@ app.post( req.body.data ) - // If the decryption failed, submission will be `null`. - if (submission) { - // Continue processing the submission - } else { - // Could not decrypt the submission - } - } -) + // Use `decryptWithAttachments` if the submission contains attachments. The result + // will contain the decrypted submission and attachments. + const submissionWithAttachments = + await formsg.crypto.decryptWithAttachments(formSecretKey, req.body.data) -// Example for submissions with attachments -app.post( - '/submissions-attachment', - // Endpoint authentication by verifying signatures - function (req, res, next) { - try { - formsg.webhooks.authenticate(req.get('X-FormSG-Signature'), POST_URI) - // Continue processing the POST body - return next() - } catch (e) { - return res.status(401).send({ message: 'Unauthorized' }) - } - }, - // Parse JSON from raw request body - express.json(), - // Decrypt the submission and attachments - async function (req, res, next) { - // Note that this function is only available from version 0.9.0 onwards - const submission = await formsg.crypto.decryptWithAttachments( - formSecretKey, - // If `verifiedContent` is provided in `req.body.data`, the return object - // will include a verified key. - req.body.data - ) - - // If the decryption failed at any point, submission will be `null`. - if (submission) { + // If the decryption failed, submission or submissionWithAttachments will be `null`. + if (submission) { // or if (submissionWithAttachments) // Continue processing the submission - - // processSubmission(submission.content) - // processAttachments(submission.attachments) } else { // Could not decrypt the submission } From a9a48c0fb049693b1f5403863fde568956d8bb65 Mon Sep 17 00:00:00 2001 From: Antariksh Date: Thu, 17 Jun 2021 11:10:43 +0800 Subject: [PATCH 3/5] docs: use HAS_ATTACHMENTS to distinguish decrypt functions --- README.md | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index cdaa3ca..f7a64cc 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,9 @@ const POST_URI = 'https://my-domain.com/submissions' // Your form's secret key downloaded from FormSG upon form creation const formSecretKey = process.env.FORM_SECRET_KEY +// Set to true if you need to download and decrypt attachments from submissions +const HAS_ATTACHMENTS = false + app.post( '/submissions', // Endpoint authentication by verifying signatures @@ -63,21 +66,14 @@ app.post( express.json(), // Decrypt the submission async function (req, res, next) { - // Use `decrypt` if the submission does not contain attachments - const submission = formsg.crypto.decrypt( - formSecretKey, - // If `verifiedContent` is provided in `req.body.data`, the return object - // will include a verified key. - req.body.data - ) - - // Use `decryptWithAttachments` if the submission contains attachments. The result - // will contain the decrypted submission and attachments. - const submissionWithAttachments = - await formsg.crypto.decryptWithAttachments(formSecretKey, req.body.data) - - // If the decryption failed, submission or submissionWithAttachments will be `null`. - if (submission) { // or if (submissionWithAttachments) + // If `verifiedContent` is provided in `req.body.data`, the return object + // will include a verified key. + const submission = HAS_ATTACHMENTS + ? await formsg.crypto.decryptWithAttachments(formSecretKey, req.body.data) + : formsg.crypto.decrypt(formSecretKey, req.body.data) + + // If the decryption failed, submission will be `null`. + if (submission) { // Continue processing the submission } else { // Could not decrypt the submission From 946358b03576b345fdad1fb60f5e5814205749e3 Mon Sep 17 00:00:00 2001 From: Antariksh Date: Thu, 17 Jun 2021 11:12:27 +0800 Subject: [PATCH 4/5] chore: lint README --- README.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f7a64cc..0fb840d 100644 --- a/README.md +++ b/README.md @@ -92,12 +92,12 @@ The underlying cryptosystem is `x25519-xsalsa20-poly1305` which is implemented b ### Format of Submission Response -| Key | Type | Description | -| ---------------- | ------ | ----------------------------------- | -| formId | string | Unique form identifier. | -| submissionId | string | Unique response identifier, displayed as 'Response ID' to form respondents | -| encryptedContent | string | The encrypted submission in base64. | -| created | string | Creation timestamp. | +| Key | Type | Description | +| ---------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------- | +| formId | string | Unique form identifier. | +| submissionId | string | Unique response identifier, displayed as 'Response ID' to form respondents | +| encryptedContent | string | The encrypted submission in base64. | +| created | string | Creation timestamp. | | attachmentDownloadUrls | Record | (Optional) Records containing field IDs and URLs where encrypted uploaded attachments can be downloaded. | ### Format of Decrypted Submissions @@ -158,17 +158,18 @@ If the decrypted content is the correct shape, then: `formsg.crypto.decryptWithAttachments(formSecretKey: string, decryptParams: DecryptParams)` (available from version 0.9.0 onwards) behaves similarly except it will return a `Promise`. -`DecryptedContentAndAttachments` is an object containing two fields: - - `content`: the standard form decrypted responses (same as the return type of `formsg.crypto.decrypt`) - - `attachments`: A `Record` containing a map of field ids of the attachment fields to a object containing the original user supplied filename and a `Uint8Array` containing the contents of the uploaded file. +`DecryptedContentAndAttachments` is an object containing two fields: + +- `content`: the standard form decrypted responses (same as the return type of `formsg.crypto.decrypt`) +- `attachments`: A `Record` containing a map of field ids of the attachment fields to a object containing the original user supplied filename and a `Uint8Array` containing the contents of the uploaded file. If the contents of any file fails to decrypt or there is a mismatch between the attachments and submission (e.g. the submission doesn't contain the original file name), then `null` will be returned. -Attachments are downloaded using S3 pre-signed URLs, with a expiry time of *one hour*. You must call `decryptWithAttachments` within this time window, or else the URL to the encrypted files will become invalid. +Attachments are downloaded using S3 pre-signed URLs, with a expiry time of _one hour_. You must call `decryptWithAttachments` within this time window, or else the URL to the encrypted files will become invalid. Attachments are end-to-end encrypted in the same way as normal form submissions, so any eavesdropper will not be able to view form attachments without your secret key. -*Warning:* We do not have the ability to scan any attachments for malicious content (e.g. spyware or viruses), so careful handling is neeeded. +_Warning:_ We do not have the ability to scan any attachments for malicious content (e.g. spyware or viruses), so careful handling is neeeded. ## Verifying Signatures Manually From c904b957e4ae90c577359d350b3b73b3fea8024e Mon Sep 17 00:00:00 2001 From: Antariksh Date: Thu, 17 Jun 2021 11:12:50 +0800 Subject: [PATCH 5/5] docs: fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0fb840d..ec08500 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ Attachments are downloaded using S3 pre-signed URLs, with a expiry time of _one Attachments are end-to-end encrypted in the same way as normal form submissions, so any eavesdropper will not be able to view form attachments without your secret key. -_Warning:_ We do not have the ability to scan any attachments for malicious content (e.g. spyware or viruses), so careful handling is neeeded. +_Warning:_ We do not have the ability to scan any attachments for malicious content (e.g. spyware or viruses), so careful handling is needed. ## Verifying Signatures Manually