Skip to content

Commit a2169be

Browse files
authored
Merge pull request #11 from mengyu-tech/my-inplace
feat: add recoverable streams for pipeline with pause/resume support
2 parents aa16a59 + 73ca886 commit a2169be

29 files changed

+1536
-3991
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Setup Node.js
1717
uses: actions/setup-node@v4
1818
with:
19-
node-version: '14' # 你项目使用的 Node.js 版本
19+
node-version: '18' # 你项目使用的 Node.js 版本
2020

2121
- name: Install Yarn
2222
run: npm install -g yarn

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Setup Node.js
1717
uses: actions/setup-node@v4
1818
with:
19-
node-version: '14' # 你项目使用的 Node.js 版本
19+
node-version: '18' # 你项目使用的 Node.js 版本
2020

2121
- name: Install Yarn
2222
run: npm install -g yarn

README.md

Lines changed: 165 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
[典枢](https://doc-dianshu.yeez.tech/index.php)的流程中,用户需要托管数据,供[Fidelius](https://github.com/YeeZTech/YeeZ-Privacy-Computing)解密、计算保证数据的正确性和隐私性,但是,用户不希望暴露源数据。因此,用户需要在本地完成加密,同样的,用户获得数据时,需要在本地进行解密(注意,此处的本地可以是网页,也可以是客户端)。meta-encryptor 就是提供给用户的加解密工具。
88

9-
109
#### 软件架构
1110

1211
使用 crypto 等加密算法。
@@ -24,7 +23,9 @@ yarn
2423
```base
2524
yarn add @yeez-tech/meta-encryptor
2625
```
26+
2727
#### 构建及测试
28+
2829
```base
2930
yarn install
3031
yarn test
@@ -37,54 +38,53 @@ yarn test
3738
生成私钥
3839

3940
```js
40-
import { crypto } from "@yeez-tech/meta-encryptor";
41+
import {crypto} from '@yeez-tech/meta-encryptor';
4142

4243
const sKey = crypto.generatePrivateKey();
4344

44-
console.log("私钥=", sKey);
45+
console.log('私钥=', sKey);
4546
const pKey = meta.crypto.generatePublicKeyFromPrivateKey(sKey);
4647
useStore().commit(ConfigMutationTypes.SET_ENCRYPTION_CONFIG, {
47-
privateKey: sKey.toString("hex"),
48-
publicKey: pKey.toString("hex"),
48+
privateKey: sKey.toString('hex'),
49+
publicKey: pKey.toString('hex')
4950
});
5051
const ypcName = meta.crypto.generateFileNameFromPKey(pKey);
5152
const ypcJson = meta.crypto.generateFileContentFromSKey(sKey);
52-
5353
```
5454

5555
##### crypto.generatePublicKeyFromPrivateKey
5656

5757
通过私钥生成公钥
5858

5959
```js
60-
import { crypto } from "@yeez-tech/meta-encryptor";
60+
import {crypto} from '@yeez-tech/meta-encryptor';
6161
const pKey = crypto.generatePublicKeyFromPrivateKey(sKey);
62-
console.log("公钥钥=", pKey);
62+
console.log('公钥钥=', pKey);
6363
```
6464

6565
##### crypto.generateFileNameFromPKey
6666

6767
通过公钥生成文件名
6868

6969
```js
70-
import { crypto } from "@yeez-tech/meta-encryptor";
70+
import {crypto} from '@yeez-tech/meta-encryptor';
7171
const ypcName = crypto.generateFileNameFromPKey(pKey);
72-
console.log("文件名=", ypcName);
72+
console.log('文件名=', ypcName);
7373
```
7474

7575
##### crypto.generateFileContentFromSKey
7676

7777
通过私钥获取密钥文件内容
7878

7979
```js
80-
import { crypto } from "@yeez-tech/meta-encryptor";
80+
import {crypto} from '@yeez-tech/meta-encryptor';
8181
const ypcJson = crypto.generateFileContentFromSKey(sKey);
82-
console.log("文件内容=", ypcJson);
82+
console.log('文件内容=', ypcJson);
8383
```
8484

85-
8685
##### Sealer
87-
推荐使用Sealer加密流,该方法支持多种格式,包括CSV,Excel,下面是对CSV的例子,其中使用了`ToString``csv()`产生的对象转换为`Buffer`
86+
87+
推荐使用 Sealer 加密流,该方法支持多种格式,包括 CSV,Excel,下面是对 CSV 的例子,其中使用了`ToString``csv()`产生的对象转换为`Buffer`
8888

8989
```js
9090
import {Sealer, ToString} from "@yeez-tech/meta-encryptor"
@@ -97,11 +97,13 @@ rs.pipe(csv())
9797
.pipe(new Sealer({keyPair:key_pair))
9898
.pipe(ws);
9999
```
100+
100101
##### Unsealer
101-
Unsealer用来解密流,并且将结果输出到流.
102+
103+
Unsealer 用来解密流,并且将结果输出到流.
102104
103105
```js
104-
import {Sealer, Unsealer, SealedFileStream} from "@yeez-tech/meta-encryptor";
106+
import {Sealer, Unsealer, SealedFileStream} from '@yeez-tech/meta-encryptor';
105107

106108
/*
107109
let src = "./tsconfig.json"
@@ -117,71 +119,205 @@ await new Promise(resolve=>{
117119
});
118120
*/
119121

120-
let unsealer = new Unsealer({keyPair:key_pair});
122+
let unsealer = new Unsealer({keyPair: key_pair});
121123
let rrs = new SealedFileStream(dst);
122-
let wws = fs.createWriteStream(src + ".new")
124+
let wws = fs.createWriteStream(src + '.new');
123125

124126
rrs.pipe(unsealer).pipe(wws);
125-
await new Promise(resolve=>{
126-
wws.on('finish', ()=>resolve());
127-
})
128-
127+
await new Promise((resolve) => {
128+
wws.on('finish', () => resolve());
129+
});
129130
```
130131
131132
##### isSealedFile
133+
132134
用于判断一个文件是否为一个有效的封装文件,如果为真,返回`true`,否则,返回`false`
135+
133136
```js
134-
import {isSealedFile} from "@yeez-tech/meta-encryptor";
137+
import {isSealedFile} from '@yeez-tech/meta-encryptor';
135138

136139
let r = isSealedFile(path);
137140
```
138141
139142
##### sealedFileVersion
143+
140144
返回封装文件的版本号。
141145
142146
```js
143-
import {sealedFileVersion} from "@yeez-tech/meta-encryptor";
147+
import {sealedFileVersion} from '@yeez-tech/meta-encryptor';
144148

145149
let r = sealedFileVersion(path);
146150
```
151+
147152
##### dataHashOfSealedFile
148-
返回封装文件对应的原始数据的hash。注意,该函数直接读取的是记录在文件头的hash,如果文件被篡改,该函数有可能返回错误的hash,因此,如果有可能,应该在解密之后,对hash进行校验。
153+
154+
返回封装文件对应的原始数据的 hash。注意,该函数直接读取的是记录在文件头的 hash,如果文件被篡改,该函数有可能返回错误的 hash,因此,如果有可能,应该在解密之后,对 hash 进行校验。
149155
150156
```js
151-
import {dataHashOfSealedFile} from "@yeez-tech/meta-encryptor";
157+
import {dataHashOfSealedFile} from '@yeez-tech/meta-encryptor';
152158

153159
let r = dataHashOfSealedFile(path);
154160
```
155161
156162
##### signedDataHash
157-
对数据hash进行签名。
163+
164+
对数据 hash 进行签名。
165+
158166
```js
159-
import {signedDataHash} from "@yeez-tech/meta-encryptor";
167+
import {signedDataHash} from '@yeez-tech/meta-encryptor';
160168

161169
//keyPair应该是{'private-key':'hex string of private key',
162170
//dataHash应该是一个Buffer,长度为32字节
163171
let r = signedDataHash(keyPair, dataHash);
164172
```
165173
166174
##### forwardSkey
175+
167176
生成转发枢私钥的信息。
177+
168178
```js
169-
import {forwardSkey} from "@yeez-tech/meta-encryptor";
179+
import {forwardSkey} from '@yeez-tech/meta-encryptor';
170180

171181
//keyPair应该是{'private-key':'hex string of private key',
172182
//dianPKey应该是一个Buffer,包含了典公钥,
173183
//enclaveHash应该是一个Buffer,包含了keyMgr的hash,可以为null,如果为null,则意味着可以被转发到任意的enclave中;
174184
let r = forwardSkey(keyPair, dianPKey, enclaveHash);
175185
```
186+
176187
返回如下对象,
188+
177189
```js
178190
{
179191
encrypted_skey:Buffer,
180192
forward_sig: Buffer
181193
}
182194
```
183195
196+
##### 可恢复流
197+
198+
meta-encryptor 提供了支持断点续传的可恢复流功能,主要包含以下组件:
199+
200+
###### RecoverableReadStream
201+
202+
用于支持断点续传的读取流,可以从指定位置恢复读取。
203+
204+
```js
205+
import {RecoverableReadStream} from '@yeez-tech/meta-encryptor';
206+
207+
const context = new PipelineContextInFile('context.dat');
208+
const readStream = new RecoverableReadStream('input.file', context);
209+
210+
readStream.pipe(someWriteStream);
211+
```
212+
213+
###### RecoverableWriteStream
214+
215+
用于支持断点续传的写入流,可以从指定位置恢复写入。
216+
217+
```js
218+
import {RecoverableWriteStream} from '@yeez-tech/meta-encryptor';
219+
220+
const context = new PipelineContextInFile('context.dat');
221+
const writeStream = new RecoverableWriteStream('output.file', context);
222+
223+
someReadStream.pipe(writeStream);
224+
```
225+
226+
###### PipelineContext
227+
228+
用于管理断点续传过程中的上下文信息的基类。
229+
230+
```js
231+
import {PipelineContext} from '@yeez-tech/meta-encryptor';
232+
233+
class MyContext extends PipelineContext {
234+
saveContext() {
235+
// 实现保存上下文的逻辑
236+
}
237+
238+
loadContext() {
239+
// 实现加载上下文的逻辑
240+
}
241+
}
242+
```
243+
244+
###### PipelineContextInFile
245+
246+
基于文件存储的上下文管理实现,支持二进制数据。
247+
248+
```js
249+
import {PipelineContextInFile} from '@yeez-tech/meta-encryptor';
250+
251+
const context = new PipelineContextInFile('context.dat');
252+
253+
// 保存上下文
254+
await context.saveContext();
255+
256+
// 加载上下文
257+
await context.loadContext();
258+
```
259+
260+
使用示例:
261+
262+
```js
263+
import {RecoverableReadStream, RecoverableWriteStream, PipelineContextInFile} from '@yeez-tech/meta-encryptor';
264+
265+
// 创建上下文管理器
266+
const context = new PipelineContextInFile('transfer.context');
267+
268+
// 创建可恢复的读写流
269+
const readStream = new RecoverableReadStream('source.file', context);
270+
const writeStream = new RecoverableWriteStream('target.file', context);
271+
272+
// 处理传输
273+
readStream.pipe(writeStream);
274+
275+
// 如果传输中断,可以使用相同的上下文重新创建流来继续传输
276+
const resumeReadStream = new RecoverableReadStream('source.file', context);
277+
const resumeWriteStream = new RecoverableWriteStream('target.file', context);
278+
resumeReadStream.pipe(resumeWriteStream);
279+
```
280+
281+
这些类提供了可靠的断点续传功能,特别适用于大文件传输或需要支持中断恢复的场景。上下文信息会被自动保存,确保传输可以从中断点准确恢复。
282+
283+
##### 断点续传解密
284+
285+
meta-encryptor 支持将可恢复流与 Unsealer 结合使用,实现加密文件的断点续传解密功能。
286+
287+
```js
288+
import {
289+
RecoverableReadStream,
290+
RecoverableWriteStream,
291+
PipelineContextInFile,
292+
Unsealer
293+
} from '@yeez-tech/meta-encryptor';
294+
295+
// 创建上下文管理器
296+
const context = new PipelineContextInFile('context.dat');
297+
await context.loadContext();
298+
299+
// 创建解密管道
300+
const readStream = new RecoverableReadStream(encryptedFile, context);
301+
const unsealer = new Unsealer({
302+
keyPair,
303+
context,
304+
progressHandler: (totalItem, readItem, bytes, writeBytes) => {
305+
console.log(`Progress: ${(bytes / (1024 * 1024)).toFixed(2)}MB`);
306+
}
307+
});
308+
const writeStream = new RecoverableWriteStream(decryptedFile, context);
309+
310+
// 连接管道并处理事件
311+
readStream.pipe(unsealer).pipe(writeStream);
312+
313+
// 如果需要暂停,可以断开管道并保存上下文
314+
readStream.unpipe(unsealer);
315+
unsealer.unpipe(writeStream);
316+
317+
// 之后可以使用相同的上下文重新创建管道继续解密
318+
```
184319
320+
这种方式特别适用于大文件解密和需要断点续传的场景。系统会自动管理解密进度和上下文信息,确保可以从任意断点恢复解密过程
185321
186322
#### Author
187323

0 commit comments

Comments
 (0)