Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32385826
D8521.1765333317.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D8521.1765333317.diff
View Options
diff --git a/keyserver/src/utils/aes-crypto-utils.js b/keyserver/src/utils/aes-crypto-utils.js
new file mode 100644
--- /dev/null
+++ b/keyserver/src/utils/aes-crypto-utils.js
@@ -0,0 +1,33 @@
+// @flow
+
+import crypto from 'crypto';
+
+import {
+ generateKeyCommon,
+ encryptCommon,
+ decryptCommon,
+} from 'lib/media/aes-crypto-utils-common.js';
+
+// crypto.webcrypto was introduced in Node 15.10.0.
+// It is not defined in Flow so we need a cast
+const commonCrypto: Crypto = (crypto: any).webcrypto;
+
+function generateKey(): Promise<Uint8Array> {
+ return generateKeyCommon(commonCrypto);
+}
+
+function encrypt(
+ keyBytes: Uint8Array,
+ plaintext: Uint8Array,
+): Promise<Uint8Array> {
+ return encryptCommon(commonCrypto, keyBytes, plaintext);
+}
+
+function decrypt(
+ keyBytes: Uint8Array,
+ sealedData: Uint8Array,
+): Promise<Uint8Array> {
+ return decryptCommon(commonCrypto, keyBytes, sealedData);
+}
+
+export { generateKey, encrypt, decrypt };
diff --git a/web/flow-typed/web-crypto.js b/lib/flow-typed/web-crypto-common.js
copy from web/flow-typed/web-crypto.js
copy to lib/flow-typed/web-crypto-common.js
--- a/web/flow-typed/web-crypto.js
+++ b/lib/flow-typed/web-crypto-common.js
@@ -279,7 +279,3 @@
| 'AES-KW',
): Promise<ArrayBuffer>;
}
-
-declare var crypto: Crypto;
-declare var msCrypto: Crypto;
-declare var webkitCrypto: Crypto;
diff --git a/lib/media/aes-crypto-utils-common.js b/lib/media/aes-crypto-utils-common.js
new file mode 100644
--- /dev/null
+++ b/lib/media/aes-crypto-utils-common.js
@@ -0,0 +1,84 @@
+// @flow
+
+const KEY_SIZE = 32; // bytes
+const IV_LENGTH = 12; // bytes - unique Initialization Vector (nonce)
+const TAG_LENGTH = 16; // bytes - GCM auth tag
+
+async function generateKeyCommon(commonCrypto: Crypto): Promise<Uint8Array> {
+ const algorithm = { name: 'AES-GCM', length: 256 };
+ const key = await commonCrypto.subtle.generateKey(algorithm, true, [
+ 'encrypt',
+ 'decrypt',
+ ]);
+ const keyData = await commonCrypto.subtle.exportKey('raw', key);
+ return new Uint8Array(keyData);
+}
+
+async function encryptCommon(
+ commonCrypto: Crypto,
+ keyBytes: Uint8Array,
+ plaintext: Uint8Array,
+): Promise<Uint8Array> {
+ if (keyBytes.length !== KEY_SIZE) {
+ throw new Error('Invalid AES key size');
+ }
+
+ // we're creating the buffer now so we can avoid reallocating it later
+ const outputBuffer = new ArrayBuffer(
+ plaintext.length + IV_LENGTH + TAG_LENGTH,
+ );
+ const ivBytes = new Uint8Array(outputBuffer, 0, IV_LENGTH);
+ const iv = commonCrypto.getRandomValues(ivBytes);
+
+ const algorithm = { name: 'AES-GCM', iv: iv, tagLength: TAG_LENGTH * 8 };
+ const key = await commonCrypto.subtle.importKey(
+ 'raw',
+ keyBytes,
+ 'AES-GCM',
+ false,
+ ['encrypt'],
+ );
+ const ciphertextWithTag = await commonCrypto.subtle.encrypt(
+ algorithm,
+ key,
+ plaintext,
+ );
+
+ const result = new Uint8Array(outputBuffer);
+ result.set(new Uint8Array(ciphertextWithTag), iv.length);
+ return result;
+}
+
+async function decryptCommon(
+ commonCrypto: Crypto,
+ keyBytes: Uint8Array,
+ sealedData: Uint8Array,
+): Promise<Uint8Array> {
+ if (keyBytes.length !== KEY_SIZE) {
+ throw new Error('Invalid AES key size');
+ }
+ if (sealedData.length < IV_LENGTH + TAG_LENGTH) {
+ throw new Error('Invalid ciphertext size');
+ }
+
+ const iv = sealedData.subarray(0, IV_LENGTH);
+ const ciphertextWithTag = sealedData.subarray(IV_LENGTH);
+
+ const algorithm = { name: 'AES-GCM', iv, tagLength: TAG_LENGTH * 8 };
+ const key = await commonCrypto.subtle.importKey(
+ 'raw',
+ keyBytes,
+ 'AES-GCM',
+ false,
+ ['decrypt'],
+ );
+
+ const plaintextBuffer = await commonCrypto.subtle.decrypt(
+ algorithm,
+ key,
+ ciphertextWithTag,
+ );
+ return new Uint8Array(plaintextBuffer);
+}
+
+export { generateKeyCommon, encryptCommon, decryptCommon };
diff --git a/web/flow-typed/web-crypto.js b/web/flow-typed/web-crypto.js
--- a/web/flow-typed/web-crypto.js
+++ b/web/flow-typed/web-crypto.js
@@ -1,285 +1,5 @@
// @flow
-declare interface RandomSource {
- getRandomValues<T: $TypedArray>(typedArray: T): T;
- randomUUID(): string;
-}
-
-declare interface Crypto extends RandomSource {
- +subtle: SubtleCrypto;
-}
-
-type CryptoKey$Type = 'secret' | 'public' | 'private';
-type CryptoKey$Usages =
- | 'encrypt'
- | 'decrypt'
- | 'sign'
- | 'verify'
- | 'deriveKey'
- | 'deriveBits'
- | 'wrapKey'
- | 'unwrapKey';
-
-declare type CryptoKey = {
- +algorithm:
- | SubtleCrypto$AesKeyGenParams
- | SubtleCrypto$RsaHashedKeyGenParams
- | SubtleCrypto$EcKeyGenParams
- | SubtleCrypto$HmacKeyGenParams,
- +extractable: boolean,
- +type: CryptoKey$Type,
- +usages: $ReadOnlyArray<CryptoKey$Usages>,
-};
-
-type SubtleCrypto$KeyFormatWithoutJwk = 'pkcs8' | 'raw' | 'spki';
-type SubtleCrypto$KeyFormat = 'jwk' | SubtleCrypto$KeyFormatWithoutJwk;
-type SubtleCrypto$HashAlgo = 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';
-type SubtleCrypto$AesAlgo = 'AES-CBC' | 'AES-CTR' | 'AES-GCM' | 'AES-KW';
-
-type SubtleCrypto$RsaOaepParams = {
- +name: 'RSA-OAEP',
- +label?: BufferSource,
-};
-
-type SubtleCrypto$AesCtrParams = {
- +name: 'AES-CTR',
- +counter: BufferSource,
- +length: number,
-};
-
-type SubtleCrypto$AesCbcParams = {
- +name: 'AES-CBC',
- +iv: BufferSource,
-};
-
-type SubtleCrypto$AesGcmParams = {
- +name: 'AES-GCM',
- +iv: BufferSource,
- +additionalData?: BufferSource,
- +tagLength?: number,
-};
-
-type SubtleCrypto$EcdhKeyDeriveParams = {
- +name: 'ECDH',
- +public: CryptoKey,
-};
-
-type SubtleCrypto$HkdfParams = {
- +name: 'HKDF',
- +hash: 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512',
- +info: BufferSource,
- +salt: BufferSource,
-};
-
-type SubtleCrypto$Pbkdf2Params = {
- +name: 'PBKDF2',
- +hash: 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512',
- +iterations: number,
- +salt: BufferSource,
-};
-
-type SubtleCrypto$HmacImportParams = {
- +name: 'HMAC',
- +hash: 'SHA-256' | 'SHA-384' | 'SHA-512',
- +length?: number,
-};
-
-type SubtleCrypto$RsaHashedKeyGenParams = {
- +name: 'RSASSA-PKCS1-v1_5' | 'RSA-PSS' | 'RSA-OAEP',
- +modulusLength: number,
- +publicExponent: Uint8Array,
- +hash: 'SHA-256' | 'SHA-384' | 'SHA-512',
-};
-
-type SubtleCrypto$HmacKeyGenParams = {
- +name: 'HMAC',
- +hash: SubtleCrypto$HashAlgo,
- +length?: number,
-};
-
-type SubtleCrypto$RsaHashedImportParams = {
- +name: 'RSASSA-PKCS1-v1_5' | 'RSA-PSS' | 'RSA-OAEP',
- +hash: 'SHA-256' | 'SHA-384' | 'SHA-512',
-};
-
-type SubtleCrypto$EcKeyImportParams = {
- +name: 'ECDSA' | 'ECDH',
- +namedCurve: 'P-256' | 'P-384' | 'P-521',
-};
-
-type SubtleCrypto$EcKeyGenParams = {
- +name: 'ECDSA' | 'ECDH',
- +namedCurve: 'P-256' | 'P-384' | 'P-521',
-};
-
-type SubtleCrypto$RsaPssParams = {
- +name: 'RSA-PSS',
- +saltLength: number,
-};
-
-type SubtleCrypto$EcdsaParams = {
- +name: 'ECDSA',
- +hash: 'SHA-256' | 'SHA-384' | 'SHA-512',
-};
-
-type SubtleCrypto$AesKeyGenParams = {
- +name: 'AES-CBC' | 'AES-CTR' | 'AES-GCM' | 'AES-KW',
- +length: 128 | 192 | 256,
-};
-
-type SubtleCrypto$ImportKeyAlgo =
- | SubtleCrypto$RsaHashedImportParams
- | SubtleCrypto$EcKeyImportParams
- | SubtleCrypto$HmacImportParams
- | SubtleCrypto$AesAlgo
- | 'PBKDF2'
- | 'HKDF';
-
-type SubtleCrypto$RsaOtherPrimesInfo = {
- +d?: string,
- +r?: string,
- +t?: string,
-};
-
-type SubtleCrypto$JsonWebKey = {
- +alg?: string,
- +crv?: string,
- +d?: string,
- +dp?: string,
- +dq?: string,
- +e?: string,
- +ext?: boolean,
- +k?: string,
- +key_ops?: $ReadOnlyArray<string>,
- +kty?: string,
- +n?: string,
- +oth?: $ReadOnlyArray<SubtleCrypto$RsaOtherPrimesInfo>,
- +p?: string,
- +q?: string,
- +qi?: string,
- +use?: string,
- +x?: string,
- +y?: string,
-};
-
-declare interface SubtleCrypto {
- decrypt(
- algorithm:
- | SubtleCrypto$RsaOaepParams
- | SubtleCrypto$AesCtrParams
- | SubtleCrypto$AesCbcParams
- | SubtleCrypto$AesGcmParams,
- key: CryptoKey,
- data: BufferSource,
- ): Promise<ArrayBuffer>;
- deriveBits(
- algorithm:
- | SubtleCrypto$EcdhKeyDeriveParams
- | SubtleCrypto$HkdfParams
- | SubtleCrypto$Pbkdf2Params,
- baseKey: CryptoKey,
- length: number,
- ): Promise<ArrayBuffer>;
- deriveKey(
- algorithm:
- | SubtleCrypto$EcdhKeyDeriveParams
- | SubtleCrypto$HkdfParams
- | SubtleCrypto$Pbkdf2Params,
- baseKey: CryptoKey,
- derivedKeyType:
- | SubtleCrypto$HmacKeyGenParams
- | SubtleCrypto$AesKeyGenParams,
- extractable: boolean,
- keyUsages: $ReadOnlyArray<CryptoKey$Usages>,
- ): Promise<CryptoKey>;
- digest(
- algorithm: SubtleCrypto$HashAlgo | { +name: SubtleCrypto$HashAlgo },
- data: BufferSource,
- ): Promise<ArrayBuffer>;
- encrypt(
- algorithm:
- | SubtleCrypto$RsaOaepParams
- | SubtleCrypto$AesCtrParams
- | SubtleCrypto$AesCbcParams
- | SubtleCrypto$AesGcmParams,
- key: CryptoKey,
- data: BufferSource,
- ): Promise<ArrayBuffer>;
- exportKey(format: 'jwk', key: CryptoKey): Promise<SubtleCrypto$JsonWebKey>;
- exportKey(
- format: SubtleCrypto$KeyFormatWithoutJwk,
- key: CryptoKey,
- ): Promise<ArrayBuffer>;
- generateKey(
- algorithm:
- | SubtleCrypto$RsaHashedKeyGenParams
- | SubtleCrypto$EcKeyGenParams
- | SubtleCrypto$HmacKeyGenParams
- | SubtleCrypto$AesKeyGenParams,
- extractable: boolean,
- keyUsages: $ReadOnlyArray<CryptoKey$Usages>,
- ): Promise<CryptoKey>;
- importKey(
- format: SubtleCrypto$KeyFormatWithoutJwk,
- keyData: BufferSource,
- algorithm: SubtleCrypto$ImportKeyAlgo,
- extractable: boolean,
- keyUsages: $ReadOnlyArray<CryptoKey$Usages>,
- ): Promise<CryptoKey>;
- importKey(
- format: 'jwk',
- keyData: SubtleCrypto$JsonWebKey,
- algorithm: SubtleCrypto$ImportKeyAlgo,
- extractable: boolean,
- keyUsages: $ReadOnlyArray<CryptoKey$Usages>,
- ): Promise<CryptoKey>;
-
- sign(
- algorithm:
- | 'RSASSA-PKCS1-v1_5'
- | 'HMAC'
- | SubtleCrypto$RsaPssParams
- | SubtleCrypto$EcdsaParams,
- key: CryptoKey,
- data: BufferSource,
- ): Promise<ArrayBuffer>;
- unwrapKey(
- format: SubtleCrypto$KeyFormat,
- wrappedKey: ArrayBuffer,
- unwrappingKey: CryptoKey,
- unwrapAlgorithm:
- | SubtleCrypto$RsaOaepParams
- | SubtleCrypto$AesCtrParams
- | SubtleCrypto$AesCbcParams
- | SubtleCrypto$AesGcmParams
- | 'AES-KW',
- unwrappedKeyAlgorithm: SubtleCrypto$ImportKeyAlgo,
- extractable: boolean,
- keyUsages: $ReadOnlyArray<CryptoKey$Usages>,
- ): Promise<CryptoKey>;
- verify(
- algorithm:
- | SubtleCrypto$RsaPssParams
- | SubtleCrypto$EcdsaParams
- | 'RSASSA-PKCS1-v1_5'
- | 'HMAC',
- key: CryptoKey,
- signature: ArrayBuffer,
- data: ArrayBuffer,
- ): Promise<boolean>;
- wrapKey(
- format: SubtleCrypto$KeyFormat,
- key: CryptoKey,
- wrappingKey: CryptoKey,
- wrapAlgorithm:
- | SubtleCrypto$RsaOaepParams
- | SubtleCrypto$AesCtrParams
- | SubtleCrypto$AesCbcParams
- | SubtleCrypto$AesGcmParams
- | 'AES-KW',
- ): Promise<ArrayBuffer>;
-}
-
declare var crypto: Crypto;
declare var msCrypto: Crypto;
declare var webkitCrypto: Crypto;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Dec 10, 2:21 AM (14 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5859924
Default Alt Text
D8521.1765333317.diff (11 KB)
Attached To
Mode
D8521: Enable webcrypto usage in keyserver codebase and unify aes crypto stack across web and the keyserver
Attached
Detach File
Event Timeline
Log In to Comment