-
Notifications
You must be signed in to change notification settings - Fork 71
/
transactions-factory.ts
142 lines (124 loc) · 4.92 KB
/
transactions-factory.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import MultiFormat from '@requestnetwork/multi-format';
import { EncryptionTypes, TransactionTypes } from '@requestnetwork/types';
import Utils from '@requestnetwork/utils';
/**
* Class to create transactions (clear and encrypted)
*/
export default class TransactionsFactory {
/**
* Creates a clear transaction with data
*
* @param data The data to create the transaction with
* @returns the transaction
*/
public static async createClearTransaction(
data: TransactionTypes.ITransactionData,
): Promise<TransactionTypes.IPersistedTransaction> {
try {
JSON.parse(data);
} catch (error) {
throw new Error('Data not parsable');
}
return { data };
}
/**
* Creates an encrypted transaction without a channel key
*
* @param data The data to create the transaction with
* @param encryptionParams Array of the encryption parameters to encrypt the key with
* @returns the encrypted transaction
*/
public static async createEncryptedTransactionInNewChannel(
data: TransactionTypes.ITransactionData,
encryptionParams: EncryptionTypes.IEncryptionParameters[],
): Promise<TransactionTypes.IPersistedTransaction> {
// format encryption method property
const encryptionMethod = `${EncryptionTypes.METHOD.ECIES}-${EncryptionTypes.METHOD.AES256_GCM}`;
// Generate a key for the AES encryption
const symmetricKey: string = await Utils.crypto.generate32BufferKey();
// Encrypt the data with the key and the AES256-GCM algorithm
const encryptedData: EncryptionTypes.IEncryptedData = await Utils.encryption.encrypt(data, {
key: symmetricKey,
method: EncryptionTypes.METHOD.AES256_GCM,
});
try {
JSON.parse(data);
} catch (error) {
throw new Error('Data not parsable');
}
// Check that all the encryption parameters given are ECIES (the only encryption method supported for now)
if (
!encryptionParams.every(
(encryptionParam: EncryptionTypes.IEncryptionParameters) =>
encryptionParam.method === EncryptionTypes.METHOD.ECIES,
)
) {
throw new Error(`encryptionParams method must be all: ${EncryptionTypes.METHOD.ECIES}`);
}
// Compute key encryption and identity hash for every encryption parameters given
const encryptedKeyAndIdentityHashesPromises = encryptionParams.map(
async (
encryptionParam: EncryptionTypes.IEncryptionParameters,
): Promise<{
encryptedKey: EncryptionTypes.IEncryptedData;
multiFormattedIdentity: string;
}> => {
const encryptedKey: EncryptionTypes.IEncryptedData = await Utils.encryption.encrypt(
symmetricKey,
encryptionParam,
);
const identityEncryption = Utils.encryption.getIdentityFromEncryptionParams(
encryptionParam,
);
const multiFormattedIdentity: string = MultiFormat.serialize(identityEncryption);
return { encryptedKey, multiFormattedIdentity };
},
);
const encryptedKeyAndIdentityHashes = await Promise.all(encryptedKeyAndIdentityHashesPromises);
// Create the encrypted keys object - Encrypted keys indexed by identity multi-format
const keys: TransactionTypes.IKeysDictionary = encryptedKeyAndIdentityHashes.reduce(
(
allKeys: TransactionTypes.IKeysDictionary,
keyAndHash: {
encryptedKey: EncryptionTypes.IEncryptedData;
multiFormattedIdentity: string;
},
): TransactionTypes.IKeysDictionary => {
const encryptedKeySerialized: string = MultiFormat.serialize(keyAndHash.encryptedKey);
allKeys[keyAndHash.multiFormattedIdentity] = encryptedKeySerialized;
return allKeys;
},
{},
);
const encryptedDataSerialized: string = MultiFormat.serialize(encryptedData);
return { encryptedData: encryptedDataSerialized, keys, encryptionMethod };
}
/**
* Creates an encrypted transaction with a channel key
*
* @param data The data to create the transaction with
* @param channelKey Channel key use to encrypt the transaction
* @returns the encrypted transaction
*/
public static async createEncryptedTransaction(
data: TransactionTypes.ITransactionData,
channelKey: EncryptionTypes.IEncryptionParameters,
): Promise<TransactionTypes.IPersistedTransaction> {
// check if the encryption method is the good one
if (channelKey.method !== EncryptionTypes.METHOD.AES256_GCM) {
throw new Error(`encryption method not supported for the channel key: ${channelKey.method}`);
}
// Encrypt the data with the key and the AES256-GCM algorithm
const encryptedData: EncryptionTypes.IEncryptedData = await Utils.encryption.encrypt(
data,
channelKey,
);
try {
JSON.parse(data);
} catch (error) {
throw new Error('Data not parsable');
}
const encryptedDataSerialized: string = MultiFormat.serialize(encryptedData);
return { encryptedData: encryptedDataSerialized };
}
}