Skip to content

Commit

Permalink
Bulk encryption decryption
Browse files Browse the repository at this point in the history
  • Loading branch information
ThibsG committed Sep 20, 2023
1 parent 9b31a89 commit 0424052
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 31 deletions.
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
subcommands: |
python3 scripts/download_wasm.py
npm install
kms-version: 4.5.0
kms-version: bulk
findex-cloud-version: 0.3.1

lint:
Expand All @@ -33,7 +33,7 @@ jobs:
with:
subcommands: |
npm test
kms-version: 4.5.0
kms-version: bulk
kms-jwe-key: '{"kty": "OKP","d": "MPEVJwdRqGM_qhJOUb5hR0Xr9EvwMLZGnkf-eDj5fU8","use": "enc","crv": "X25519","kid": "DX3GC+Fx3etxfRJValQNbqaB0gs=","x":
"gdF-1TtAjsFqNWr9nwhGUlFG38qrDUqYgcILgtYrpTY","alg": "ECDH-ES"}'
findex-cloud-version: 0.3.1
Expand All @@ -50,7 +50,7 @@ jobs:
extension: so
destination: linux-x86-64
os: ubuntu-20.04
kms-version: 4.5.0
kms-version: bulk
findex-cloud-version: 0.3.1
copy_fresh_build: false
copy_regression_files: |
Expand All @@ -64,7 +64,7 @@ jobs:
with:
branch: develop
target: x86_64-unknown-linux-gnu
kms-version: 4.5.0
kms-version: bulk
copy_fresh_build: false
copy_regression_files: |
cp ./cloudproof_js/non_regression_vector.json tests/data/cover_crypt/non_regression/js_non_regression_vector.json
Expand Down Expand Up @@ -95,7 +95,7 @@ jobs:
sleep 5
cd ../test
node chrome.mjs http://localhost:8090 http://kms:9998
kms-version: 4.5.0
kms-version: bulk
findex-cloud-version: 0.3.1

example_reactjs:
Expand All @@ -110,7 +110,7 @@ jobs:
sleep 5
cd ../test
node chrome.mjs http://localhost:8090 http://kms:9998
kms-version: 4.5.0
kms-version: bulk
findex-cloud-version: 0.3.1

example_browser:
Expand All @@ -123,7 +123,7 @@ jobs:
python3 -m http.server &
sleep 3
node test.mjs
kms-version: 4.5.0
kms-version: bulk
findex-cloud-version: 0.3.1

example_webpack:
Expand All @@ -143,7 +143,7 @@ jobs:
cd examples/nodejs
npm install
node test.mjs 10
kms-version: 4.5.0
kms-version: bulk
findex-cloud-version: 0.3.1

example_imdb:
Expand Down
5 changes: 2 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ version: '3'
services:
kms:
container_name: kms
image: ghcr.io/cosmian/kms:4.5.0
image: ghcr.io/cosmian/kms:bulk
ports:
- 9998:9998
environment:
JWK_PRIVATE_KEY: '{"kty": "OKP","d": "MPEVJwdRqGM_qhJOUb5hR0Xr9EvwMLZGnkf-eDj5fU8","use": "enc","crv": "X25519","kid": "DX3GC+Fx3etxfRJValQNbqaB0gs=","x":
"gdF-1TtAjsFqNWr9nwhGUlFG38qrDUqYgcILgtYrpTY","alg": "ECDH-ES"}'
JWK_PRIVATE_KEY: '{"kty": "OKP","d": "MPEVJwdRqGM_qhJOUb5hR0Xr9EvwMLZGnkf-eDj5fU8","use": "enc","crv": "X25519","kid": "DX3GC+Fx3etxfRJValQNbqaB0gs=","x": "gdF-1TtAjsFqNWr9nwhGUlFG38qrDUqYgcILgtYrpTY","alg": "ECDH-ES"}'
findex_cloud:
image: ghcr.io/cosmian/findex_cloud:0.1.0
ports:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"eslint-plugin-n": "^15.2.5",
"eslint-plugin-promise": "^6.0.1",
"prettier": "2.7.1",
"puppeteer": "^19.2.0",
"puppeteer": "^19.11.1",
"redis": "^4.3.1",
"rollup": "^3.3.0",
"typescript": "^4.9.0",
Expand Down
112 changes: 105 additions & 7 deletions src/kms/kms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ReKeyKeyPair } from "./requests/ReKeyKeyPair"
import { Revoke } from "./requests/Revoke"
import {
Attributes,
CryptographicParameters,
Link,
LinkType,
VendorAttributes,
Expand All @@ -37,6 +38,7 @@ import {
CryptographicUsageMask,
RevocationReasonEnumeration,
} from "./structs/types"
import { webassembly_split_encrypted_header } from "pkg/cover_crypt/cloudproof_cover_crypt"

// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
export interface KmsRequest<TResponse> {
Expand Down Expand Up @@ -570,6 +572,7 @@ export class KmsClient {
* Mark a CoverCrypt Secret Master Key as Revoked
* @param {string} uniqueIdentifier the unique identifier of the key
* @param {string} reason the explanation of the revocation
* @returns nothing
*/
public async revokeCoverCryptSecretMasterKey(
uniqueIdentifier: string,
Expand All @@ -582,6 +585,7 @@ export class KmsClient {
* Mark a CoverCrypt Public Master Key as Revoked
* @param {string} uniqueIdentifier the unique identifier of the key
* @param {string} reason the explanation of the revocation
* @returns nothing
*/
public async revokeCoverCryptPublicMasterKey(
uniqueIdentifier: string,
Expand Down Expand Up @@ -677,6 +681,7 @@ export class KmsClient {
* Mark a CoverCrypt User Decryption Key as Revoked
* @param {string} uniqueIdentifier the unique identifier of the key
* @param {string} reason the explanation of the revocation
* @returns nothing
*/
public async revokeCoverCryptUserDecryptionKey(
uniqueIdentifier: string,
Expand All @@ -693,16 +698,17 @@ export class KmsClient {
* @param {object} options Additional optional options to the encryption
* @param {Uint8Array} options.headerMetadata Data encrypted in the header
* @param {Uint8Array} options.authenticationData Data use to authenticate the encrypted value when decrypting (if use, should be use during decryption)
* @returns one or multiple ciphertexts
*/
public async coverCryptEncrypt(
uniqueIdentifier: string,
accessPolicy: string,
data: Uint8Array,
data: Uint8Array | Uint8Array[],
options: {
headerMetadata?: Uint8Array
authenticationData?: Uint8Array
} = {},
): Promise<Uint8Array> {
): Promise<Uint8Array | Uint8Array[]> {
const accessPolicyBytes = new TextEncoder().encode(accessPolicy)
const accessPolicySize = encode(accessPolicyBytes.length)

Expand All @@ -713,6 +719,28 @@ export class KmsClient {
headerMetadata = options.headerMetadata
}

const cryptographicParameters = new CryptographicParameters()

if (data instanceof Uint8Array) {
cryptographicParameters.cryptographicAlgorithm =
CryptographicAlgorithm.CoverCrypt
} else {
cryptographicParameters.cryptographicAlgorithm =
CryptographicAlgorithm.CoverCryptBulk

let plaintext = encode(data.length)

for (const chunk of data) {
plaintext = Uint8Array.from([
...plaintext,
...encode(chunk.length),
...chunk,
])
}

data = plaintext
}

const dataToEncrypt = Uint8Array.from([
...accessPolicySize,
...accessPolicyBytes,
Expand All @@ -721,12 +749,39 @@ export class KmsClient {
...data,
])

const encrypt = new Encrypt(uniqueIdentifier, dataToEncrypt)
const encrypt = new Encrypt(
uniqueIdentifier,
dataToEncrypt,
cryptographicParameters,
)
if (typeof options.authenticationData !== "undefined") {
encrypt.authenticatedEncryptionAdditionalData = options.authenticationData
}

return (await this.post(encrypt)).data
const encryptedData = (await this.post(encrypt)).data

if (
cryptographicParameters.cryptographicAlgorithm ===
CryptographicAlgorithm.CoverCrypt
) {
return encryptedData
}

const { encryptedHeader, ciphertext } =
webassembly_split_encrypted_header(encryptedData)

let { result: nbChunks, tail: tailPlaintext } = decode(ciphertext)

const encryptedChunks = []
for (let i = 0; i < nbChunks; i++) {
const { result: chunkSize, tail } = decode(tailPlaintext)
const chunk = tail.slice(0, chunkSize)
tailPlaintext = tail.slice(chunkSize)

encryptedChunks.push(new Uint8Array([...encryptedHeader, ...chunk]))
}

return encryptedChunks
}

/**
Expand All @@ -735,14 +790,40 @@ export class KmsClient {
* @param data to decrypt
* @param {object} options Additional optional options to the encryption
* @param {Uint8Array} options.authenticationData Data use to authenticate the encrypted value when decrypting (if use, should have been use during encryption)
* @returns header metadata and plaintext
*/
public async coverCryptDecrypt(
uniqueIdentifier: string,
data: Uint8Array,
data: Uint8Array | Uint8Array[],
options: {
authenticationData?: Uint8Array
} = {},
): Promise<{ headerMetadata: Uint8Array; plaintext: Uint8Array }> {
): Promise<{
headerMetadata: Uint8Array
plaintext: Uint8Array | Uint8Array[]
}> {
const cryptographicParameters = new CryptographicParameters()

if (data instanceof Uint8Array) {
cryptographicParameters.cryptographicAlgorithm =
CryptographicAlgorithm.CoverCrypt
} else {
cryptographicParameters.cryptographicAlgorithm =
CryptographicAlgorithm.CoverCryptBulk

let ciphertext = encode(data.length)

for (const chunk of data) {
ciphertext = Uint8Array.from([
...ciphertext,
...encode(chunk.length),
...chunk,
])
}

data = ciphertext
}

const decrypt = new Decrypt(uniqueIdentifier, data)
if (typeof options.authenticationData !== "undefined") {
decrypt.authenticatedEncryptionAdditionalData = options.authenticationData
Expand All @@ -752,7 +833,24 @@ export class KmsClient {

const { result: headerMetadataLength, tail } = decode(response.data)
const headerMetadata = tail.slice(0, headerMetadataLength)
const plaintext = tail.slice(headerMetadataLength)
let plaintext: Uint8Array | Uint8Array[] = tail.slice(headerMetadataLength)

if (
cryptographicParameters.cryptographicAlgorithm ===
CryptographicAlgorithm.CoverCryptBulk
) {
let { result: nbChunks, tail: tailPlaintext } = decode(plaintext)
const decryptedChunks = []
for (let i = 0; i < nbChunks; i++) {
const { result: chunkSize, tail } = decode(tailPlaintext)
const chunk = tail.slice(0, chunkSize)
tailPlaintext = tail.slice(chunkSize)

decryptedChunks.push(chunk)

plaintext = decryptedChunks
}
}

return { headerMetadata, plaintext }
}
Expand Down
2 changes: 1 addition & 1 deletion src/kms/structs/object_data_structures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export enum CryptographicAlgorithm {
TFHE = 0x8880_0002,
ABE = 0x8880_0003,
CoverCrypt = 0x8880_0004,
FPEFF1 = 0x8880_0005,
CoverCryptBulk = 0x8880_0005,
}

export class KeyBlock {
Expand Down
Loading

0 comments on commit 0424052

Please sign in to comment.