Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit ac1efc3

Browse files
committed
EIT-2337 | add encryption module
1 parent b89752a commit ac1efc3

12 files changed

+166
-4
lines changed

.vscode/settings.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,8 @@
55
"editor.codeActionsOnSave": {
66
"source.organizeImports": true,
77
"source.fixAll.eslint": true
8-
}
8+
},
9+
"cSpell.words": [
10+
"ciphertext"
11+
]
912
}

src/client.ts

+18
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import { AnchorService } from './anchor/service/anchor.service'
44
import { NetworkConfiguration } from './config/entity/configuration.entity'
55
import Network from './config/entity/networks.entity'
66
import { ConfigService } from './config/service/config.service'
7+
import { EncryptData } from './encryption/entity/encrypt_data'
8+
import { EncryptionService } from './encryption/service/encryption.service'
79
import { HttpClient } from './infrastructure/http.client'
810
import { Proof } from './proof/entity/proof.entity'
911
import { ProofService } from './proof/service/proof.service'
1012
import { RecordReceipt } from './record/entity/record-receipt.entity'
1113
import { Record } from './record/entity/record.entity'
1214
import { RecordService } from './record/service/record.service'
1315
import { DependencyInjection } from './shared/dependency-injection'
16+
import { TypedArray } from './shared/utils'
1417

1518
/**
1619
* Entrypoint to the Bloock SDK:
@@ -28,6 +31,8 @@ export class BloockClient {
2831

2932
private httpClient: HttpClient
3033

34+
private encryptionService: EncryptionService
35+
3136
/**
3237
* Constructor with API Key that enables accessing to Bloock's functionalities.
3338
* @param {string} apiKey Client API Key.
@@ -40,6 +45,7 @@ export class BloockClient {
4045
this.configService = container.resolve<ConfigService>('ConfigService')
4146
this.recordService = container.resolve<RecordService>('RecordService')
4247
this.proofService = container.resolve<ProofService>('ProofService')
48+
this.encryptionService = container.resolve<EncryptionService>('EncryptionService')
4349

4450
this.httpClient = container.resolve<HttpClient>('HttpClient')
4551

@@ -159,4 +165,16 @@ export class BloockClient {
159165
public async verifySignatures(records: Record[]): Promise<boolean> {
160166
return this.proofService.verifySignatures(records)
161167
}
168+
169+
public async generateSecretKey(): Promise<string> {
170+
return this.encryptionService.generateSecretKey()
171+
}
172+
173+
public async encryptData(data: TypedArray, secret: string): Promise<EncryptData> {
174+
return this.encryptionService.encrypt(data, secret)
175+
}
176+
177+
public async decryptData(encrypt_data: EncryptData, secret: string): Promise<TypedArray> {
178+
return this.encryptionService.decrypt(encrypt_data, secret)
179+
}
162180
}

src/encryption/entity/encrypt_data.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
export class EncryptData {
3+
public ciphertext: string;
4+
public iv: string;
5+
public tag: string;
6+
public protect?: string;
7+
public encrypted_key?: string;
8+
public header?: Headers
9+
10+
constructor(
11+
ciphertext: string,
12+
iv: string,
13+
tag: string,
14+
protect?: string,
15+
encrypted_key?: string,
16+
header?: Headers
17+
) {
18+
this.ciphertext = ciphertext;
19+
this.iv = iv;
20+
this.tag = tag;
21+
this.protect = protect;
22+
this.encrypted_key = encrypted_key;
23+
this.header = header
24+
}
25+
}
26+
27+
type Headers = {
28+
alg?: string
29+
[propName: string]: unknown
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { inject, injectable } from "tsyringe"
2+
import { EncryptionClient } from "../../infrastructure/encryption.client"
3+
import { TypedArray } from "../../shared/utils"
4+
import { EncryptData } from "../entity/encrypt_data"
5+
import { EncryptionRepository } from "./encryption.repository"
6+
7+
@injectable()
8+
export class EncryptionRepositoryImpl implements EncryptionRepository {
9+
constructor(
10+
@inject('EncryptionClient') private encryptionClient: EncryptionClient,
11+
) {}
12+
13+
async encrypt(data: TypedArray, secret: string): Promise<EncryptData> {
14+
const ed = await this.encryptionClient.encrypt(data, secret)
15+
return new EncryptData(ed.ciphertext, ed.iv, ed.tag, ed.protect, ed.encrypted_key, ed.header)
16+
}
17+
18+
async decrypt(encrypt_data: EncryptData, secret: string): Promise<TypedArray> {
19+
const dd = await this.encryptionClient.decrypt(encrypt_data, secret)
20+
return dd
21+
}
22+
23+
async generateSecretKey(): Promise<string> {
24+
const k = await this.encryptionClient.generateSecretKey()
25+
return k
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { TypedArray } from "../../shared/utils"
2+
import { EncryptData } from "../entity/encrypt_data"
3+
4+
5+
export interface EncryptionRepository {
6+
encrypt(data: TypedArray, secret: string): Promise<EncryptData>
7+
decrypt(encrypt_data: EncryptData, secret: string): Promise<TypedArray>
8+
generateSecretKey(): Promise<string>
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { inject, injectable } from 'tsyringe';
2+
import { TypedArray } from "../../shared/utils";
3+
import { EncryptData } from "../entity/encrypt_data";
4+
import { EncryptionRepository } from '../repository/encryption.repository';
5+
import { EncryptionService } from "./encryption.service";
6+
7+
@injectable()
8+
export class EncryptionServiceImpl implements EncryptionService {
9+
constructor(
10+
@inject('EncryptionRepository') private encryptionRepository: EncryptionRepository
11+
) {}
12+
13+
async encrypt(data: TypedArray, secret: string): Promise<EncryptData> {
14+
const ed = await this.encryptionRepository.encrypt(data, secret)
15+
return ed
16+
}
17+
18+
async decrypt(encrypt_data: EncryptData, secret: string): Promise<TypedArray> {
19+
const dd = await this.encryptionRepository.decrypt(encrypt_data, secret)
20+
return dd
21+
}
22+
23+
async generateSecretKey(): Promise<string> {
24+
const k = await this.encryptionRepository.generateSecretKey()
25+
return k
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { TypedArray } from "../../shared/utils"
2+
import { EncryptData } from "../entity/encrypt_data"
3+
4+
export interface EncryptionService {
5+
encrypt(data: TypedArray, secret: string): Promise<EncryptData>
6+
decrypt(encrypt_data: EncryptData, secret: string): Promise<TypedArray>
7+
generateSecretKey(): Promise<string>
8+
}

src/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import 'reflect-metadata'
22
import { BloockClient } from './client'
33
import { NetworkConfiguration } from './config/entity/configuration.entity'
44
import Network from './config/entity/networks.entity'
5+
import { EncryptData } from './encryption/entity/encrypt_data'
56
import { Proof } from './proof/entity/proof.entity'
67
import { RecordReceipt } from './record/entity/record-receipt.entity'
78
import { Record } from './record/entity/record.entity'
89

9-
export { BloockClient, Record, RecordReceipt, Proof, Network, NetworkConfiguration }
10+
export { BloockClient, Record, RecordReceipt, Proof, Network, NetworkConfiguration, EncryptData }

src/infrastructure/encryption/jwe.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import * as jose from 'jose';
2+
import { injectable } from 'tsyringe';
23
import { ConfigData } from '../../config/repository/config-data';
34
import { TypedArray } from "../../shared/utils";
45
import { Encryption, EncryptionClient, Headers } from "../encryption.client";
56

6-
7+
@injectable()
78
export class JWEClient implements EncryptionClient {
9+
810
async encrypt(payload: TypedArray, rawSecretKey: string): Promise<Encryption> {
911
const configData = new ConfigData()
1012

src/shared/dependency-injection.ts

+14
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { AnchorServiceImpl } from '../anchor/service/anchor-impl.service'
44
import { ConfigData } from '../config/repository/config-data'
55
import { ConfigRepositoryImpl } from '../config/repository/config-impl.repository'
66
import { ConfigServiceImpl } from '../config/service/config-impl.service'
7+
import { EncryptionRepositoryImpl } from '../encryption/repository/encryption-impl.repository'
8+
import { EncryptionServiceImpl } from '../encryption/service/encryption-impl.service'
79
import { Web3Client } from '../infrastructure/blockchain/web3'
10+
import { JWEClient } from '../infrastructure/encryption/jwe'
811
import { Keccak } from '../infrastructure/hashing/keccak'
912
import { HttpData } from '../infrastructure/http/http-data'
1013
import { HttpClientImpl } from '../infrastructure/http/http-impl'
@@ -60,5 +63,16 @@ export class DependencyInjection {
6063
container.register('ProofService', {
6164
useClass: ProofServiceImpl
6265
})
66+
67+
// Encryption module
68+
container.register('EncryptionRepository', {
69+
useClass: EncryptionRepositoryImpl
70+
})
71+
container.register('EncryptionService', {
72+
useClass: EncryptionServiceImpl
73+
})
74+
container.register('EncryptionClient', {
75+
useClass: JWEClient
76+
})
6377
}
6478
}

test/acceptance.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ describe('Acceptance Tests', () => {
3131
jest.setTimeout(120000)
3232

3333
const sdk = getSdk()
34-
34+
3535
const records = [Record.fromString(randHex(64))]
3636

3737
const sendReceipt = await sdk.sendRecords(records)

test/functional.test.ts

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import fs from 'fs'
12
import { BloockClient, Network, Record, RecordReceipt } from '../src'
23
import { Anchor } from '../src/anchor/entity/anchor.entity'
4+
import { PDFDocument } from '../src/record/entity/document/pdf'
35

46
function getSdk(): BloockClient {
57
const apiKey = process.env['API_KEY'] || ''
@@ -117,4 +119,25 @@ describe('Functional Tests', () => {
117119
let timestamp = await sdk.validateRoot(root, Network.BLOOCK_CHAIN)
118120
expect(timestamp).toBeGreaterThan(0)
119121
})
122+
123+
test('testEncryptDocument', async () => {
124+
jest.setTimeout(120000)
125+
126+
const sdk = getSdk()
127+
128+
const bytes = fs.readFileSync('./test/assets/dummy.pdf')
129+
let file = new PDFDocument(bytes)
130+
await file.ready
131+
132+
const secretKey = await sdk.generateSecretKey()
133+
expect(secretKey).toBeTruthy()
134+
135+
let encryptedData = await sdk.encryptData(file.getDataBytes(), secretKey)
136+
expect(encryptedData).toBeTruthy()
137+
expect(encryptedData.ciphertext).toBeTruthy()
138+
139+
let decryptedData = await sdk.decryptData(encryptedData, secretKey)
140+
expect(decryptedData).toBeTruthy()
141+
expect(decryptedData).toEqual(file.getDataBytes())
142+
})
120143
})

0 commit comments

Comments
 (0)