Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3523103
D9940.id33577.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D9940.id33577.diff
View Options
diff --git a/keyserver/src/push/crypto.js b/keyserver/src/push/crypto.js
--- a/keyserver/src/push/crypto.js
+++ b/keyserver/src/push/crypto.js
@@ -1,6 +1,7 @@
// @flow
import apn from '@parse/node-apn';
+import crypto from 'crypto';
import invariant from 'invariant';
import _cloneDeep from 'lodash/fp/cloneDeep.js';
@@ -8,6 +9,7 @@
PlainTextWebNotification,
WebNotification,
} from 'lib/types/notif-types.js';
+import { toBase64URL } from 'lib/utils/base64.js';
import type {
AndroidNotification,
@@ -16,6 +18,7 @@
NotificationTargetDevice,
} from './types.js';
import { encryptAndUpdateOlmSession } from '../updaters/olm-session-updater.js';
+import { encrypt, generateKey } from '../utils/aes-crypto-utils.js';
import { getOlmUtility } from '../utils/olm-utils.js';
async function encryptIOSNotification(
@@ -378,10 +381,37 @@
return Promise.all(notificationPromises);
}
+async function encryptBlobPayload(payload: string): Promise<{
+ +encryptionKey: string,
+ +encryptedPayload: Blob,
+ +encryptedPayloadHash: string,
+}> {
+ const encryptionKey = await generateKey();
+ const encryptedPayload = await encrypt(
+ encryptionKey,
+ new TextEncoder().encode(payload),
+ );
+ const encryptedPayloadBuffer = Buffer.from(encryptedPayload);
+ const blobHashBase64 = await crypto
+ .createHash('sha256')
+ .update(encryptedPayloadBuffer)
+ .digest('base64');
+ const blobHash = toBase64URL(blobHashBase64);
+
+ const payloadBlob = new Blob([encryptedPayloadBuffer]);
+ const encryptionKeyString = Buffer.from(encryptionKey).toString('base64');
+ return {
+ encryptionKey: encryptionKeyString,
+ encryptedPayload: payloadBlob,
+ encryptedPayloadHash: blobHash,
+ };
+}
+
export {
prepareEncryptedIOSNotifications,
prepareEncryptedIOSNotificationRescind,
prepareEncryptedAndroidNotifications,
prepareEncryptedAndroidNotificationRescinds,
prepareEncryptedWebNotifications,
+ encryptBlobPayload,
};
diff --git a/keyserver/src/push/utils.js b/keyserver/src/push/utils.js
--- a/keyserver/src/push/utils.js
+++ b/keyserver/src/push/utils.js
@@ -5,12 +5,14 @@
import invariant from 'invariant';
import nodeFetch from 'node-fetch';
import type { Response } from 'node-fetch';
+import uuid from 'uuid';
import webpush from 'web-push';
import type { PlatformDetails } from 'lib/types/device-types.js';
import { threadSubscriptions } from 'lib/types/subscription-types.js';
import { threadPermissions } from 'lib/types/thread-permission-types.js';
+import { encryptBlobPayload } from './crypto.js';
import {
getAPNPushProfileForCodeVersion,
getFCMPushProfileForCodeVersion,
@@ -389,7 +391,20 @@
}
| { +blobUploadError: string },
> {
- return upload(payload);
+ const blobHolder = uuid.v4();
+ try {
+ const { encryptionKey, encryptedPayload, encryptedPayloadHash } =
+ await encryptBlobPayload(payload);
+ await upload(encryptedPayload, encryptedPayloadHash, blobHolder);
+ return {
+ blobHash: encryptedPayloadHash,
+ encryptionKey,
+ };
+ } catch (e) {
+ return {
+ blobUploadError: e.message,
+ };
+ }
}
export {
diff --git a/keyserver/src/services/blob.js b/keyserver/src/services/blob.js
--- a/keyserver/src/services/blob.js
+++ b/keyserver/src/services/blob.js
@@ -1,48 +1,21 @@
// @flow
-import crypto from 'crypto';
-import uuid from 'uuid';
-
import blobService from 'lib/facts/blob-service.js';
-import { toBase64URL } from 'lib/utils/base64.js';
import { makeBlobServiceEndpointURL } from 'lib/utils/blob-service.js';
import { getMessageForException } from 'lib/utils/errors.js';
-import { encrypt, generateKey } from '../utils/aes-crypto-utils.js';
-
-async function upload(payload: string): Promise<
- | {
- +blobHash: string,
- +encryptionKey: string,
- }
- | { +blobUploadError: string },
-> {
- const encryptionKey = await generateKey();
- const encryptedPayloadBuffer = Buffer.from(
- await encrypt(encryptionKey, new TextEncoder().encode(payload)),
- );
-
- const blobHolder = uuid.v4();
- const blobHashBase64 = await crypto
- .createHash('sha256')
- .update(encryptedPayloadBuffer)
- .digest('base64');
-
- const blobHash = toBase64URL(blobHashBase64);
-
+async function upload(blob: Blob, hash: string, holder: string): Promise<void> {
const formData = new FormData();
- const payloadBlob = new Blob([encryptedPayloadBuffer]);
-
- formData.append('blob_hash', blobHash);
- formData.append('blob_data', payloadBlob);
+ formData.append('blob_hash', hash);
+ formData.append('blob_data', blob);
const assignHolderPromise = fetch(
makeBlobServiceEndpointURL(blobService.httpEndpoints.ASSIGN_HOLDER),
{
method: blobService.httpEndpoints.ASSIGN_HOLDER.method,
body: JSON.stringify({
- holder: blobHolder,
- blob_hash: blobHash,
+ holder,
+ blob_hash: hash,
}),
headers: {
'content-type': 'application/json',
@@ -58,38 +31,31 @@
},
);
+ let assignHolderResponse, uploadBlobResponse;
try {
- const [assignHolderResponse, uploadBlobResponse] = await Promise.all([
+ [assignHolderResponse, uploadBlobResponse] = await Promise.all([
assignHolderPromise,
uploadHolderPromise,
]);
-
- if (!assignHolderResponse.ok) {
- const { status, statusText } = assignHolderResponse;
- return {
- blobUploadError: `Holder assignment failed with HTTP ${status}: ${statusText}`,
- };
- }
-
- if (!uploadBlobResponse.ok) {
- const { status, statusText } = uploadBlobResponse;
- return {
- blobUploadError: `Payload upload failed with HTTP ${status}: ${statusText}`,
- };
- }
} catch (e) {
- return {
- blobUploadError: `Payload upload failed with: ${
+ throw new Error(
+ `Payload upload failed with: ${
getMessageForException(e) ?? 'unknown error'
}`,
- };
+ );
}
- const encryptionKeyString = Buffer.from(encryptionKey).toString('base64');
- return {
- blobHash,
- encryptionKey: encryptionKeyString,
- };
+ if (!assignHolderResponse.ok) {
+ const { status, statusText } = assignHolderResponse;
+ throw new Error(
+ `Holder assignment failed with HTTP ${status}: ${statusText}`,
+ );
+ }
+
+ if (!uploadBlobResponse.ok) {
+ const { status, statusText } = uploadBlobResponse;
+ throw new Error(`Payload upload failed with HTTP ${status}: ${statusText}`);
+ }
}
export { upload };
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Dec 24, 8:23 AM (15 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2699200
Default Alt Text
D9940.id33577.diff (6 KB)
Attached To
Mode
D9940: [keyserver] Split blob encryption and upload into separate functions
Attached
Detach File
Event Timeline
Log In to Comment