@aiot-toolkit/aiotpack 2.0.2 → 2.0.3-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/lib/afterCompile/ux/UxAfterCompile.d.ts +1 -1
  2. package/lib/afterCompile/ux/UxAfterCompile.js +295 -243
  3. package/lib/afterCompile/xts/entryTemplate.js +111 -113
  4. package/lib/afterCompile/xts/generateRpk.js +25 -54
  5. package/lib/afterCompile/xts/ts2wasm.js +62 -63
  6. package/lib/afterWorks/ux/UxAfterWorks.js +12 -19
  7. package/lib/beforeCompile/ux/UxBeforeCompile.js +26 -28
  8. package/lib/beforeCompile/xts/preInstall.js +50 -55
  9. package/lib/beforeWorks/ux/UxBeforeWorks.js +12 -19
  10. package/lib/compiler/enum/CompileMode.js +16 -23
  11. package/lib/compiler/interface/ICompileParam.js +1 -2
  12. package/lib/compiler/interface/ICompiler.js +1 -2
  13. package/lib/compiler/interface/ISignConfig.js +1 -2
  14. package/lib/compiler/javascript/JavascriptCompiler.js +147 -154
  15. package/lib/compiler/javascript/JavascriptDefaultCompileOption.js +20 -16
  16. package/lib/compiler/javascript/android/AndroidWebpackConfigurator.js +13 -11
  17. package/lib/compiler/javascript/android/plugin/WrapPlugin.js +53 -49
  18. package/lib/compiler/javascript/interface/IJavascriptCompileOption.js +1 -2
  19. package/lib/compiler/javascript/interface/IWebpackConfigurator.js +4 -1
  20. package/lib/compiler/javascript/vela/VelaWebpackConfigurator.js +78 -75
  21. package/lib/compiler/javascript/vela/enum/BuildNameFormatType.js +30 -41
  22. package/lib/compiler/javascript/vela/enum/EntryType.js +15 -29
  23. package/lib/compiler/javascript/vela/interface/IChunk.js +4 -1
  24. package/lib/compiler/javascript/vela/interface/IManifest.js +1 -2
  25. package/lib/compiler/javascript/vela/interface/IQuickAppConfig.js +1 -2
  26. package/lib/compiler/javascript/vela/model/Package.js +80 -51
  27. package/lib/compiler/javascript/vela/plugin/WrapPlugin.js +31 -27
  28. package/lib/compiler/javascript/vela/utils/Jsc.js +30 -33
  29. package/lib/compiler/javascript/vela/utils/UxCompileUtil.js +152 -130
  30. package/lib/compiler/javascript/vela/utils/ZipUtil.d.ts +10 -2
  31. package/lib/compiler/javascript/vela/utils/ZipUtil.js +282 -267
  32. package/lib/compiler/javascript/vela/utils/signature/Base64.js +65 -67
  33. package/lib/compiler/javascript/vela/utils/signature/CRC32.js +37 -35
  34. package/lib/compiler/javascript/vela/utils/signature/SignUtil.js +755 -731
  35. package/lib/compiler/javascript/vela/utils/signature/Signer.js +24 -22
  36. package/lib/compiler/javascript/vela/utils/webpackLoader/addColSourceMap.js +47 -52
  37. package/lib/compiler/javascript/vela/utils/webpackLoader/extractMapData.js +21 -17
  38. package/lib/config/UxConfig.js +145 -173
  39. package/lib/config/XtsConfig.d.ts +2 -0
  40. package/lib/config/XtsConfig.js +30 -39
  41. package/lib/index.js +88 -41
  42. package/lib/interface/ICompileOptions.js +5 -2
  43. package/lib/interface/IDeviceList.js +1 -2
  44. package/lib/loader/ux/JsLoader.js +32 -30
  45. package/lib/loader/ux/PngLoader.js +47 -53
  46. package/lib/loader/ux/android/UxLoader.d.ts +2 -0
  47. package/lib/loader/ux/android/UxLoader.js +30 -32
  48. package/lib/loader/ux/vela/AppUxLoader.d.ts +2 -0
  49. package/lib/loader/ux/vela/AppUxLoader.js +23 -25
  50. package/lib/loader/ux/vela/HmlLoader.js +59 -55
  51. package/lib/loader/ux/vela/UxLoader.d.ts +2 -0
  52. package/lib/loader/ux/vela/UxLoader.js +29 -37
  53. package/lib/loader/xts/XtsLoader.js +55 -41
  54. package/lib/utils/BeforeCompileUtils.js +100 -95
  55. package/lib/utils/PngUtils.js +42 -36
  56. package/lib/utils/ux/ManifestSchema.js +198 -194
  57. package/lib/utils/ux/UxFileUtils.d.ts +3 -3
  58. package/lib/utils/ux/UxFileUtils.js +130 -125
  59. package/lib/utils/ux/UxLoaderUtils.js +292 -307
  60. package/lib/utils/ux/android/AndroidUx.js +88 -90
  61. package/lib/utils/xts/XtsFileLaneUtils.js +58 -65
  62. package/lib/utils/xts/XtsFollowWorks.js +122 -129
  63. package/package.json +6 -6
@@ -1,764 +1,788 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- const shared_utils_1 = require("@aiot-toolkit/shared-utils");
16
- const crypto_1 = __importDefault(require("crypto"));
17
- const fs_extra_1 = __importDefault(require("fs-extra"));
18
- const jsrsasign_1 = __importDefault(require("jsrsasign"));
19
- const jszip_1 = __importDefault(require("jszip"));
20
- const path_1 = __importDefault(require("path"));
21
- const CompileMode_1 = __importDefault(require("../../../../enum/CompileMode"));
22
- const ZipUtil_1 = __importDefault(require("../ZipUtil"));
23
- const Base64_1 = __importDefault(require("./Base64"));
24
- const CRC32_1 = __importDefault(require("./CRC32"));
25
- const Signer_1 = __importDefault(require("./Signer"));
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _sharedUtils = require("@aiot-toolkit/shared-utils");
8
+ var _crypto = _interopRequireDefault(require("crypto"));
9
+ var _fsExtra = _interopRequireDefault(require("fs-extra"));
10
+ var _jsrsasign = _interopRequireDefault(require("jsrsasign"));
11
+ var _jszip = _interopRequireDefault(require("jszip"));
12
+ var _path = _interopRequireDefault(require("path"));
13
+ var _CompileMode = _interopRequireDefault(require("../../../../enum/CompileMode"));
14
+ var _ZipUtil = _interopRequireDefault(require("../ZipUtil"));
15
+ var _Base = _interopRequireDefault(require("./Base64"));
16
+ var _CRC = _interopRequireDefault(require("./CRC32"));
17
+ var _Signer = _interopRequireDefault(require("./Signer"));
18
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
26
19
  /**
27
20
  * SignUtil
28
21
  */
29
22
  class SignUtil {
30
- /**
31
- * 获取签名相关的配置内容
32
- * @param param IJavascriptCompileOption参数中获取签名目录等内容
33
- * @returns
34
- */
35
- static getProjectSignConfig(param) {
36
- const { mode, projectPath, signRoot } = param;
37
- const signPathFolder = path_1.default.join(projectPath, signRoot || 'sign');
38
- const signPathConfig = {
39
- debug: {
40
- privatekey: path_1.default.join(signPathFolder, 'debug', 'private.pem'),
41
- certificate: path_1.default.join(signPathFolder, 'debug', 'certificate.pem')
42
- },
43
- sign: {
44
- privatekey: path_1.default.join(signPathFolder, 'private.pem'),
45
- certificate: path_1.default.join(signPathFolder, 'certificate.pem')
46
- },
47
- defaultDevelopment: {
48
- privatekey: path_1.default.join(__dirname, 'pem', 'private.pem'),
49
- certificate: path_1.default.join(__dirname, 'pem', 'certificate.pem')
50
- },
51
- oldRelease: {
52
- privatekey: path_1.default.join(signPathFolder, 'release', 'private.pem'),
53
- certificate: path_1.default.join(signPathFolder, 'release', 'certificate.pem')
54
- }
55
- };
56
- // build模式 优先sign/debug/证书 其次sign/证书 最后toolkit中默认的证书
57
- const developmentSignConfig = [
58
- signPathConfig.debug,
59
- signPathConfig.sign,
60
- signPathConfig.defaultDevelopment
61
- ];
62
- // release模式 优先sign/release/证书 其次sign/证书
63
- const releaseSignConfig = [signPathConfig.oldRelease, signPathConfig.sign];
64
- let modeSignConfig = [];
65
- let signConfig;
66
- switch (mode) {
67
- case CompileMode_1.default.DEVELOPMENT:
68
- modeSignConfig = developmentSignConfig;
69
- break;
70
- case CompileMode_1.default.PRODUCTION:
71
- modeSignConfig = releaseSignConfig;
72
- break;
73
- default:
74
- // 打印信息, 模式未定义
75
- shared_utils_1.ColorConsole.error(`Error: mode ${mode} undefined`);
76
- break;
77
- }
78
- // 寻找有效的证书路径
79
- const findPath = modeSignConfig.find(({ privatekey, certificate }) => shared_utils_1.FileUtil.checkFilePath([privatekey, certificate]));
80
- if (findPath) {
81
- let { privatekey: privatekeyPath, certificate: certificatePath } = findPath;
82
- shared_utils_1.ColorConsole.info('privatekeyPath is ', {
83
- word: privatekeyPath
84
- }, `\ncertificatePath is `, {
85
- word: certificatePath
86
- });
87
- // 读取证书内容
88
- signConfig = {
89
- privatekey: fs_extra_1.default.readFileSync(privatekeyPath),
90
- certificate: fs_extra_1.default.readFileSync(certificatePath)
91
- };
92
- }
93
- else {
94
- // 抛出错误,在指定模式下未找到证书
95
- throw new Error(`The current mode is ${mode}, and there is a problem with the certification path`);
96
- }
97
- return signConfig;
23
+ /**
24
+ * 获取签名相关的配置内容
25
+ * @param param IJavascriptCompileOption参数中获取签名目录等内容
26
+ * @returns
27
+ */
28
+ static getProjectSignConfig(param) {
29
+ const {
30
+ mode,
31
+ projectPath,
32
+ signRoot
33
+ } = param;
34
+ const signPathFolder = _path.default.join(projectPath, signRoot || 'sign');
35
+ const signPathConfig = {
36
+ debug: {
37
+ privatekey: _path.default.join(signPathFolder, 'debug', 'private.pem'),
38
+ certificate: _path.default.join(signPathFolder, 'debug', 'certificate.pem')
39
+ },
40
+ sign: {
41
+ privatekey: _path.default.join(signPathFolder, 'private.pem'),
42
+ certificate: _path.default.join(signPathFolder, 'certificate.pem')
43
+ },
44
+ defaultDevelopment: {
45
+ privatekey: _path.default.join(__dirname, 'pem', 'private.pem'),
46
+ certificate: _path.default.join(__dirname, 'pem', 'certificate.pem')
47
+ },
48
+ oldRelease: {
49
+ privatekey: _path.default.join(signPathFolder, 'release', 'private.pem'),
50
+ certificate: _path.default.join(signPathFolder, 'release', 'certificate.pem')
51
+ }
52
+ };
53
+ // build模式 优先sign/debug/证书 其次sign/证书 最后toolkit中默认的证书
54
+ const developmentSignConfig = [signPathConfig.debug, signPathConfig.sign, signPathConfig.defaultDevelopment];
55
+ // release模式 优先sign/release/证书 其次sign/证书
56
+ const releaseSignConfig = [signPathConfig.oldRelease, signPathConfig.sign];
57
+ let modeSignConfig = [];
58
+ let signConfig;
59
+ switch (mode) {
60
+ case _CompileMode.default.DEVELOPMENT:
61
+ modeSignConfig = developmentSignConfig;
62
+ break;
63
+ case _CompileMode.default.PRODUCTION:
64
+ modeSignConfig = releaseSignConfig;
65
+ break;
66
+ default:
67
+ // 打印信息, 模式未定义
68
+ _sharedUtils.ColorConsole.error(`Error: mode ${mode} undefined`);
69
+ break;
98
70
  }
99
- /**
100
- * 对二进制zipBuffer签名
101
- *
102
- * 1. 对`META-INF/CERT`做签名,并生成新的`META-INF/CERT` buffer
103
- * 2. "新`META-INF/CERT` + 其它文件"生成新的 zipBuffer
104
- * 3. 对“新zipBuffer”,做整体签名
105
- * @param zipBuffer
106
- * @param privatekey
107
- * @param certificate
108
- * @returns
109
- */
110
- static signPackage(target, privatekey, certificate) {
111
- return __awaiter(this, void 0, void 0, function* () {
112
- var _a;
113
- const getFileBuffer = (path) => {
114
- return target.getResource(path);
115
- };
116
- // 摘要 和 文件列表
117
- const fileDigestHash = [];
118
- const fileList = [];
119
- // 1
120
- const metaBuffer = (_a = getFileBuffer(ZipUtil_1.default.CERT_PATH)) === null || _a === void 0 ? void 0 : _a.fileContentBuffer;
121
- if (metaBuffer) {
122
- const metaHash = {
123
- name: ZipUtil_1.default.DIGEST_HASH_JSON,
124
- hash: shared_utils_1.CommonUtil.calcDataDigest(metaBuffer)
125
- };
126
- const signedMetaBuffer = SignUtil.doSign(metaBuffer, [metaHash], privatekey, certificate);
127
- if (signedMetaBuffer === false) {
128
- // META-INF/CERT签名失败
129
- shared_utils_1.ColorConsole.throw('META-INF/CERT signature failed');
130
- }
131
- else {
132
- fileList.push({
133
- path: ZipUtil_1.default.CERT_PATH,
134
- content: signedMetaBuffer
135
- });
136
- fileDigestHash.push({
137
- name: ZipUtil_1.default.CERT_PATH,
138
- hash: shared_utils_1.CommonUtil.calcDataDigest(signedMetaBuffer)
139
- });
140
- }
141
- }
142
- // 2
143
- const files = target.resourceList;
144
- files
145
- .map((item) => {
146
- return {
147
- path: item.fileBuildPath,
148
- content: item.fileContentBuffer
149
- };
150
- })
151
- .filter(SignUtil.fileFilter)
152
- .map((item) => {
153
- fileList.push(item);
154
- fileDigestHash.push({
155
- name: item.path,
156
- hash: shared_utils_1.CommonUtil.calcDataDigest(item.content)
157
- });
158
- });
159
- // 因为META变化,重新创建ZIP流
160
- const newZipBuffer = yield ZipUtil_1.default.createZipBufferFromFileList(fileList, target.comment);
161
- // 3
162
- const signedZipBuffer = SignUtil.doSign(newZipBuffer, fileDigestHash, privatekey, certificate);
163
- if (signedZipBuffer === false) {
164
- // 签名失败
165
- shared_utils_1.ColorConsole.throw('package signature failed');
166
- }
167
- return signedZipBuffer;
168
- });
71
+ // 寻找有效的证书路径
72
+ const findPath = modeSignConfig.find(_ref => {
73
+ let {
74
+ privatekey,
75
+ certificate
76
+ } = _ref;
77
+ return _sharedUtils.FileUtil.checkFilePath([privatekey, certificate]);
78
+ });
79
+ if (findPath) {
80
+ let {
81
+ privatekey: privatekeyPath,
82
+ certificate: certificatePath
83
+ } = findPath;
84
+ _sharedUtils.ColorConsole.info('privatekeyPath is ', {
85
+ word: privatekeyPath
86
+ }, `\ncertificatePath is `, {
87
+ word: certificatePath
88
+ });
89
+ // 读取证书内容
90
+ signConfig = {
91
+ privatekey: _fsExtra.default.readFileSync(privatekeyPath),
92
+ certificate: _fsExtra.default.readFileSync(certificatePath)
93
+ };
94
+ } else {
95
+ // 抛出错误,在指定模式下未找到证书
96
+ throw new Error(`The current mode is ${mode}, and there is a problem with the certification path`);
169
97
  }
170
- /**
171
- * 根据ZIP流获取文件实例
172
- *
173
- * 1. zipbuffer转换为JSZip对象
174
- * 2. 提取文件列表,并生成每个文件的 buffer
175
- * 3. 创建获取文件buffer的函数
176
- *
177
- * @param zipBuffer
178
- * @returns
179
- */
180
- static createFileListFromZipBuffer(zipBuffer) {
181
- return __awaiter(this, void 0, void 0, function* () {
182
- const zipInst = yield jszip_1.default.loadAsync(zipBuffer, ZipUtil_1.default.ZIP_OPTION);
183
- function iterator(filePath) {
184
- return __awaiter(this, void 0, void 0, function* () {
185
- const content = yield zipInst.files[filePath].async('nodebuffer');
186
- return {
187
- path: filePath,
188
- content
189
- };
190
- });
191
- }
192
- const fileList = yield Promise.all(Object.keys(zipInst.files).map(iterator));
193
- return {
194
- fileList,
195
- comment: zipInst.comment,
196
- getFileBuffer(path) {
197
- const buffer = fileList.find((item) => item.path === path);
198
- return buffer === null || buffer === void 0 ? void 0 : buffer.content;
199
- }
200
- };
98
+ return signConfig;
99
+ }
100
+
101
+ /**
102
+ * 对二进制zipBuffer签名
103
+ *
104
+ * 1. 对`META-INF/CERT`做签名,并生成新的`META-INF/CERT` buffer
105
+ * 2. "新`META-INF/CERT` + 其它文件"生成新的 zipBuffer
106
+ * 3. 对“新zipBuffer”,做整体签名
107
+ * @param zipBuffer
108
+ * @param privatekey
109
+ * @param certificate
110
+ * @returns
111
+ */
112
+ static async signPackage(target, privatekey, certificate) {
113
+ const getFileBuffer = path => {
114
+ return target.getResource(path);
115
+ };
116
+
117
+ // 摘要 和 文件列表
118
+ const fileDigestHash = [];
119
+ const fileList = [];
120
+
121
+ // 1
122
+ const metaBuffer = getFileBuffer(_ZipUtil.default.CERT_PATH)?.fileContentBuffer;
123
+ if (metaBuffer) {
124
+ const metaHash = {
125
+ name: _ZipUtil.default.DIGEST_HASH_JSON,
126
+ hash: _sharedUtils.CommonUtil.calcDataDigest(metaBuffer)
127
+ };
128
+ const signedMetaBuffer = SignUtil.doSign(metaBuffer, [metaHash], privatekey, certificate);
129
+ if (signedMetaBuffer === false) {
130
+ // META-INF/CERT签名失败
131
+ _sharedUtils.ColorConsole.throw('META-INF/CERT signature failed');
132
+ } else {
133
+ fileList.push({
134
+ path: _ZipUtil.default.CERT_PATH,
135
+ content: signedMetaBuffer
201
136
  });
137
+ fileDigestHash.push({
138
+ name: _ZipUtil.default.CERT_PATH,
139
+ hash: _sharedUtils.CommonUtil.calcDataDigest(signedMetaBuffer)
140
+ });
141
+ }
202
142
  }
203
- /**
204
- * zip buffer 签名,返回签名后的buffer
205
- *
206
- * @description 根据zipBuffer + zip的文件列表 + 私钥 + 证书,对 zipbuffer 签名
207
- * @param fileBuffer
208
- * @param files
209
- * @param privatekey
210
- * @param certificate
211
- */
212
- static doSign(fileBuffer, files, privatekey, certificate) {
213
- const result = SignUtil.unZipFiles(fileBuffer, files);
214
- if (!result) {
215
- return false;
216
- }
217
- const [chunks] = result;
218
- // 生成整体签名
219
- SignUtil.signChunk(chunks, privatekey, certificate);
220
- // 写入zip文件
221
- const signContent = SignUtil.saveChunk(fileBuffer, chunks);
222
- return signContent;
223
- }
224
- /**
225
- * 解析buffer
226
- * @param fileBuffer
227
- * @param files
228
- */
229
- static unZipFiles(fileBuffer, files) {
230
- // 1. 读取zip文件
231
- if (!fileBuffer || fileBuffer.length <= 4) {
232
- shared_utils_1.ColorConsole.error('Zip file open failed');
233
- return false;
234
- }
235
- // 2. 检查文件格式是否正确
236
- const fileMagic = fileBuffer.readInt32LE(0);
237
- if (fileMagic !== 0x4034b50) {
238
- shared_utils_1.ColorConsole.error('Zip file format is wrong');
239
- return false;
240
- }
241
- // 3. 解析数据块
242
- const chunks = SignUtil.parserZip(fileBuffer);
243
- chunks.options = { files };
244
- // 解析成功,生成签名块
245
- if (chunks.tag) {
246
- // 分别处理三个签名块
247
- Object.keys(chunks.sections).forEach((item) => {
248
- const chunk = chunks.sections[item];
249
- SignUtil.processChunk(fileBuffer, chunk);
250
- });
251
- return [chunks, fileBuffer];
252
- }
253
- return false;
143
+ // 2
144
+ const files = target.resourceList;
145
+ files.map(item => {
146
+ return {
147
+ path: item.fileBuildPath,
148
+ content: item.fileContentBuffer
149
+ };
150
+ }).filter(SignUtil.fileFilter).map(item => {
151
+ fileList.push(item);
152
+ fileDigestHash.push({
153
+ name: item.path,
154
+ hash: _sharedUtils.CommonUtil.calcDataDigest(item.content)
155
+ });
156
+ });
157
+ // 因为META变化,重新创建ZIP流
158
+ const newZipBuffer = await _ZipUtil.default.createZipBufferFromFileList(fileList, target.comment);
159
+ // 3
160
+ const signedZipBuffer = SignUtil.doSign(newZipBuffer, fileDigestHash, privatekey, certificate);
161
+ if (signedZipBuffer === false) {
162
+ // 签名失败
163
+ _sharedUtils.ColorConsole.throw('package signature failed');
254
164
  }
255
- /**
256
- * 解析ZIP 分解为数据块
257
- * @param fileBuffer
258
- */
259
- static parserZip(fileBuffer) {
260
- let chunk = {
261
- signchunk: Buffer.from(''),
262
- tag: false,
263
- length: fileBuffer.length,
264
- options: {
265
- files: []
266
- },
267
- sections: {
268
- header: {
269
- tag: false,
270
- startIndex: 0,
271
- len: 0,
272
- previous: 0,
273
- sign: undefined
274
- },
275
- central: {
276
- tag: false,
277
- startIndex: 0,
278
- len: 0,
279
- previous: 0,
280
- sign: undefined
281
- },
282
- footer: {
283
- tag: false,
284
- startIndex: 0,
285
- len: 0,
286
- previous: 0,
287
- sign: undefined
288
- }
289
- }
290
- };
291
- // fileBuffer至少22个字节
292
- chunk.sections.footer = SignUtil.readEOCD(fileBuffer);
293
- if (chunk.sections.footer.tag) {
294
- chunk.sections.central = SignUtil.readCD(fileBuffer, chunk.sections.footer.previous, chunk.sections.footer.startIndex - chunk.sections.footer.previous);
295
- if (chunk.sections.central.tag) {
296
- chunk.sections.header = SignUtil.readFH(fileBuffer, chunk.sections.central.previous, chunk.sections.central.startIndex - chunk.sections.central.previous);
297
- if (chunk.sections.header.tag) {
298
- chunk.tag = true;
299
- }
300
- }
301
- }
302
- return chunk;
165
+ return signedZipBuffer;
166
+ }
167
+ /**
168
+ * 根据ZIP流获取文件实例
169
+ *
170
+ * 1. zipbuffer转换为JSZip对象
171
+ * 2. 提取文件列表,并生成每个文件的 buffer
172
+ * 3. 创建获取文件buffer的函数
173
+ *
174
+ * @param zipBuffer
175
+ * @returns
176
+ */
177
+ static async createFileListFromZipBuffer(zipBuffer) {
178
+ const zipInst = await _jszip.default.loadAsync(zipBuffer, _ZipUtil.default.ZIP_OPTION);
179
+ async function iterator(filePath) {
180
+ const content = await zipInst.files[filePath].async('nodebuffer');
181
+ return {
182
+ path: filePath,
183
+ content
184
+ };
303
185
  }
304
- /**
305
- * 从后往前读取buffer,读取尾部buffer
306
- * @param buffer
307
- * @returns
308
- */
309
- static readEOCD(buffer) {
310
- let chunk;
311
- if (buffer && buffer.length >= 22) {
312
- let offset = buffer.length - 22;
313
- let tag;
314
- // 从开始位置往前单个字节读取,检查
315
- while (offset >= 0) {
316
- tag = buffer.readInt32LE(offset);
317
- if (tag === 0x6054b50) {
318
- // 如果找到起始位置
319
- chunk = {
320
- tag: true,
321
- startIndex: offset,
322
- len: buffer.length - offset,
323
- previous: buffer.readInt32LE(offset + 16)
324
- };
325
- break;
326
- }
327
- offset -= 1;
328
- }
329
- }
330
- return chunk;
186
+ const fileList = await Promise.all(Object.keys(zipInst.files).map(iterator));
187
+ return {
188
+ fileList,
189
+ comment: zipInst.comment,
190
+ getFileBuffer(path) {
191
+ const buffer = fileList.find(item => item.path === path);
192
+ return buffer?.content;
193
+ }
194
+ };
195
+ }
196
+ /**
197
+ * zip buffer 签名,返回签名后的buffer
198
+ *
199
+ * @description 根据zipBuffer + zip的文件列表 + 私钥 + 证书,对 zipbuffer 签名
200
+ * @param fileBuffer
201
+ * @param files
202
+ * @param privatekey
203
+ * @param certificate
204
+ */
205
+ static doSign(fileBuffer, files, privatekey, certificate) {
206
+ const result = SignUtil.unZipFiles(fileBuffer, files);
207
+ if (!result) {
208
+ return false;
331
209
  }
332
- /**
333
- * 读取中部buffer
334
- * @param buffer
335
- * @param offset
336
- * @param size
337
- */
338
- static readCD(buffer, offset, size) {
339
- let chunk;
340
- if (buffer && buffer.length >= offset) {
341
- const tag = buffer.readInt32LE(offset);
342
- // 找到起始位置
343
- if (tag === 0x2014b50) {
344
- chunk = {
345
- tag: true,
346
- startIndex: offset,
347
- len: size,
348
- previous: buffer.readInt32LE(offset + 42)
349
- };
350
- }
351
- }
352
- return chunk;
210
+ const [chunks] = result;
211
+
212
+ // 生成整体签名
213
+ SignUtil.signChunk(chunks, privatekey, certificate);
214
+ // 写入zip文件
215
+ const signContent = SignUtil.saveChunk(fileBuffer, chunks);
216
+ return signContent;
217
+ }
218
+ /**
219
+ * 解析buffer
220
+ * @param fileBuffer
221
+ * @param files
222
+ */
223
+ static unZipFiles(fileBuffer, files) {
224
+ // 1. 读取zip文件
225
+ if (!fileBuffer || fileBuffer.length <= 4) {
226
+ _sharedUtils.ColorConsole.error('Zip file open failed');
227
+ return false;
353
228
  }
354
- /**
355
- * 读取前部buffer
356
- * @param buffer
357
- * @param offset
358
- * @param size
359
- * @returns
360
- */
361
- static readFH(buffer, offset, size) {
362
- let chunk;
363
- if (buffer && buffer.length >= offset) {
364
- const tag = buffer.readInt32LE(offset);
365
- // 找到起始位置
366
- if (tag === 0x4034b50) {
367
- chunk = {
368
- tag: true,
369
- startIndex: offset,
370
- len: size,
371
- previous: -1
372
- };
373
- }
374
- }
375
- return chunk;
229
+ // 2. 检查文件格式是否正确
230
+ const fileMagic = fileBuffer.readInt32LE(0);
231
+ if (fileMagic !== 0x4034b50) {
232
+ _sharedUtils.ColorConsole.error('Zip file format is wrong');
233
+ return false;
376
234
  }
377
- /**
378
- * 数据块hash
379
- * @param buffer
380
- * @param chunk
381
- */
382
- static processChunk(buffer, chunk) {
383
- const cur = chunk.startIndex;
384
- const end = chunk.startIndex + chunk.len;
385
- // 取数据块对应的buffer内容
386
- const chk = buffer.subarray(cur, end);
387
- // 创建指定长度Buffer对象,并确保分配内存区域被清零
388
- const header = Buffer.alloc(5 + chunk.len);
389
- // 给第一个字节赋值
390
- header[0] = 0xa5;
391
- // 从第二个字节位置开始填充,长度为4字节,填充内容为chk.length
392
- header.writeInt32LE(chk.length, 1);
393
- // 从第六个开始填充chk的内容
394
- chk.copy(header, 5);
395
- // 将buffer进行hash计算并存储到chunk对象上
396
- const signer = crypto_1.default.createHash('SHA256');
397
- signer.update(header);
398
- chunk.sign = signer.digest();
235
+ // 3. 解析数据块
236
+ const chunks = SignUtil.parserZip(fileBuffer);
237
+ chunks.options = {
238
+ files
239
+ };
240
+ // 解析成功,生成签名块
241
+ if (chunks.tag) {
242
+ // 分别处理三个签名块
243
+ Object.keys(chunks.sections).forEach(item => {
244
+ const chunk = chunks.sections[item];
245
+ SignUtil.processChunk(fileBuffer, chunk);
246
+ });
247
+ return [chunks, fileBuffer];
399
248
  }
400
- static signChunk(chunks, privatekey, certificate) {
401
- const { sections } = chunks;
402
- // 二进制拼接每个块摘要
403
- let length = 5;
404
- if (sections.header.sign) {
405
- length += sections.header.sign.length;
249
+ return false;
250
+ }
251
+ /**
252
+ * 解析ZIP 分解为数据块
253
+ * @param fileBuffer
254
+ */
255
+ static parserZip(fileBuffer) {
256
+ let chunk = {
257
+ signchunk: Buffer.from(''),
258
+ tag: false,
259
+ length: fileBuffer.length,
260
+ options: {
261
+ files: []
262
+ },
263
+ sections: {
264
+ header: {
265
+ tag: false,
266
+ startIndex: 0,
267
+ len: 0,
268
+ previous: 0,
269
+ sign: undefined
270
+ },
271
+ central: {
272
+ tag: false,
273
+ startIndex: 0,
274
+ len: 0,
275
+ previous: 0,
276
+ sign: undefined
277
+ },
278
+ footer: {
279
+ tag: false,
280
+ startIndex: 0,
281
+ len: 0,
282
+ previous: 0,
283
+ sign: undefined
406
284
  }
407
- if (sections.central.sign) {
408
- length += sections.central.sign.length;
285
+ }
286
+ };
287
+ // fileBuffer至少22个字节
288
+ chunk.sections.footer = SignUtil.readEOCD(fileBuffer);
289
+ if (chunk.sections.footer.tag) {
290
+ chunk.sections.central = SignUtil.readCD(fileBuffer, chunk.sections.footer.previous, chunk.sections.footer.startIndex - chunk.sections.footer.previous);
291
+ if (chunk.sections.central.tag) {
292
+ chunk.sections.header = SignUtil.readFH(fileBuffer, chunk.sections.central.previous, chunk.sections.central.startIndex - chunk.sections.central.previous);
293
+ if (chunk.sections.header.tag) {
294
+ chunk.tag = true;
409
295
  }
410
- if (sections.footer.sign) {
411
- length += sections.footer.sign.length;
412
- }
413
- const wholeData = Buffer.alloc(length);
414
- let offset = 0;
415
- wholeData.writeInt8(0x5a, 0);
416
- wholeData.writeInt32LE(3, 1);
417
- offset += 5;
418
- function writeBuffer(buf) {
419
- buf.copy(wholeData, offset);
420
- offset += buf.length;
296
+ }
297
+ }
298
+ return chunk;
299
+ }
300
+ /**
301
+ * 从后往前读取buffer,读取尾部buffer
302
+ * @param buffer
303
+ * @returns
304
+ */
305
+ static readEOCD(buffer) {
306
+ let chunk;
307
+ if (buffer && buffer.length >= 22) {
308
+ let offset = buffer.length - 22;
309
+ let tag;
310
+ // 从开始位置往前单个字节读取,检查
311
+ while (offset >= 0) {
312
+ tag = buffer.readInt32LE(offset);
313
+ if (tag === 0x6054b50) {
314
+ // 如果找到起始位置
315
+ chunk = {
316
+ tag: true,
317
+ startIndex: offset,
318
+ len: buffer.length - offset,
319
+ previous: buffer.readInt32LE(offset + 16)
320
+ };
321
+ break;
421
322
  }
422
- sections.header.sign && writeBuffer(sections.header.sign);
423
- sections.central.sign && writeBuffer(sections.central.sign);
424
- sections.footer.sign && writeBuffer(sections.footer.sign);
425
- // 计算整体摘要
426
- const signer = crypto_1.default.createHash('SHA256');
427
- signer.update(wholeData);
428
- const signature = signer.digest();
429
- // 生成sign block, 计算block总长度, 向buf中考入数据
430
- const signchunk = SignUtil.makeSignChunk(chunks.options, signature, privatekey, certificate);
431
- chunks.signchunk = SignUtil.saveSignChunk(signchunk);
323
+ offset -= 1;
324
+ }
432
325
  }
433
- static makeSignChunk(options, sign, privatekey, certificate) {
434
- // 提取公钥
435
- const cert = Buffer.from(Base64_1.default.unarmor(certificate));
436
- const c = new jsrsasign_1.default.X509();
437
- c.readCertPEM(certificate.toString());
438
- const pubKey = jsrsasign_1.default.KEYUTIL.getPEM(c.getPublicKey());
439
- // 摘要块
440
- const digestBuf = Buffer.alloc(sign.length + 12);
441
- digestBuf.writeInt32LE(sign.length + 8, 0);
442
- digestBuf.writeInt32LE(0x0103, 4);
443
- digestBuf.writeInt32LE(sign.length, 8);
444
- sign.copy(digestBuf, 12);
445
- const digestBlock = {
446
- len: digestBuf.length,
447
- buffer: digestBuf
448
- };
449
- // 证书块
450
- const certBuf = Buffer.alloc(cert.length + 4);
451
- certBuf.writeInt32LE(cert.length, 0);
452
- cert.copy(certBuf, 4);
453
- const certBlock = {
454
- len: certBuf.length,
455
- buffer: certBuf
456
- };
457
- // 签名数据
458
- const signdataBlock = {
459
- len: 12,
460
- digests: {
461
- size: 0,
462
- data: []
463
- },
464
- certs: {
465
- size: 0,
466
- data: []
467
- },
468
- additional: 0
469
- };
470
- signdataBlock.digests.data.push(digestBlock);
471
- signdataBlock.digests.size += digestBlock.len;
472
- signdataBlock.len += digestBlock.len;
473
- signdataBlock.certs.data.push(certBlock);
474
- signdataBlock.certs.size += certBlock.len;
475
- signdataBlock.len += certBlock.len;
476
- // 将public.pem转化为der
477
- const pubbuf = Buffer.from(Base64_1.default.unarmor(pubKey));
478
- const signBlock = {
479
- len: 16 + pubbuf.length,
480
- size: 12 + pubbuf.length,
481
- signdata: {
482
- size: 0,
483
- buffer: null
484
- },
485
- signatures: {
486
- size: 0,
487
- data: []
488
- },
489
- pubkey: {
490
- size: pubbuf.length,
491
- buffer: pubbuf
492
- }
493
- };
494
- signBlock.signdata.buffer = SignUtil.makeSignDataBuffer(signdataBlock);
495
- signBlock.signdata.size = signdataBlock.len;
496
- signBlock.size += signdataBlock.len;
497
- signBlock.len += signdataBlock.len;
498
- // 生成签名
499
- const signature = SignUtil.callCryptoSignFunction(signBlock.signdata.buffer, privatekey, certificate);
500
- const signatureBlock = {
501
- len: signature.length + 12,
502
- size: signature.length + 8,
503
- id: 0x0103,
504
- buffer: signature
326
+ return chunk;
327
+ }
328
+ /**
329
+ * 读取中部buffer
330
+ * @param buffer
331
+ * @param offset
332
+ * @param size
333
+ */
334
+ static readCD(buffer, offset, size) {
335
+ let chunk;
336
+ if (buffer && buffer.length >= offset) {
337
+ const tag = buffer.readInt32LE(offset);
338
+ // 找到起始位置
339
+ if (tag === 0x2014b50) {
340
+ chunk = {
341
+ tag: true,
342
+ startIndex: offset,
343
+ len: size,
344
+ previous: buffer.readInt32LE(offset + 42)
505
345
  };
506
- signBlock.signatures.data.push(signatureBlock);
507
- signBlock.signatures.size += signatureBlock.len;
508
- signBlock.size += signatureBlock.len;
509
- signBlock.len += signatureBlock.len;
510
- const signBlocks = {
511
- len: 4,
512
- size: 0,
513
- data: []
514
- };
515
- signBlocks.data.push(signBlock);
516
- signBlocks.size += signBlock.len;
517
- signBlocks.len += signBlock.len;
518
- // 生成key-value
519
- const kvBlock = {
520
- len: signBlocks.len + 12,
521
- size: signBlocks.len + 4,
522
- id: 0x01000101,
523
- value: signBlocks
524
- };
525
- const signchunk = {
526
- len: 32,
527
- size: 24,
528
- data: []
346
+ }
347
+ }
348
+ return chunk;
349
+ }
350
+ /**
351
+ * 读取前部buffer
352
+ * @param buffer
353
+ * @param offset
354
+ * @param size
355
+ * @returns
356
+ */
357
+ static readFH(buffer, offset, size) {
358
+ let chunk;
359
+ if (buffer && buffer.length >= offset) {
360
+ const tag = buffer.readInt32LE(offset);
361
+ // 找到起始位置
362
+ if (tag === 0x4034b50) {
363
+ chunk = {
364
+ tag: true,
365
+ startIndex: offset,
366
+ len: size,
367
+ previous: -1
529
368
  };
530
- signchunk.data.push(kvBlock);
531
- signchunk.size += kvBlock.len;
532
- signchunk.len += kvBlock.len;
533
- // 添加文件列表hash kvblock
534
- if (options.files) {
535
- const filehashChunk = SignUtil.signFiles(options.files, privatekey, certificate);
536
- if (filehashChunk) {
537
- const filesignBlocks = {
538
- len: 4,
539
- size: 0,
540
- data: []
541
- };
542
- filesignBlocks.data.push(filehashChunk);
543
- filesignBlocks.size += filehashChunk.length;
544
- filesignBlocks.len += filehashChunk.length;
545
- const filekvBlock = {
546
- len: filesignBlocks.len + 12,
547
- size: filesignBlocks.len + 4,
548
- id: 0x01000201,
549
- value: filesignBlocks
550
- };
551
- signchunk.data.push(filekvBlock);
552
- signchunk.size += filekvBlock.len;
553
- signchunk.len += filekvBlock.len;
554
- }
555
- }
556
- return signchunk;
369
+ }
557
370
  }
558
- static makeSignDataBuffer(block) {
559
- const buffer = Buffer.alloc(block.len);
560
- let offset = 0;
561
- buffer.writeInt32LE(block.digests.size, offset);
562
- offset += 4;
563
- block.digests.data.forEach((item) => {
564
- item.buffer.copy(buffer, offset);
565
- offset += item.len;
566
- });
567
- buffer.writeInt32LE(block.certs.size, offset);
568
- offset += 4;
569
- block.certs.data.forEach((item) => {
570
- item.buffer.copy(buffer, offset);
571
- offset += item.len;
572
- });
573
- buffer.writeInt32LE(block.additional, offset);
574
- return buffer;
371
+ return chunk;
372
+ }
373
+ /**
374
+ * 数据块hash
375
+ * @param buffer
376
+ * @param chunk
377
+ */
378
+ static processChunk(buffer, chunk) {
379
+ const cur = chunk.startIndex;
380
+ const end = chunk.startIndex + chunk.len;
381
+ // 取数据块对应的buffer内容
382
+ const chk = buffer.subarray(cur, end);
383
+ // 创建指定长度Buffer对象,并确保分配内存区域被清零
384
+ const header = Buffer.alloc(5 + chunk.len);
385
+ // 给第一个字节赋值
386
+ header[0] = 0xa5;
387
+ // 从第二个字节位置开始填充,长度为4字节,填充内容为chk.length
388
+ header.writeInt32LE(chk.length, 1);
389
+ // 从第六个开始填充chk的内容
390
+ chk.copy(header, 5);
391
+
392
+ // 将buffer进行hash计算并存储到chunk对象上
393
+ const signer = _crypto.default.createHash('SHA256');
394
+ signer.update(header);
395
+ chunk.sign = signer.digest();
396
+ }
397
+ static signChunk(chunks, privatekey, certificate) {
398
+ const {
399
+ sections
400
+ } = chunks;
401
+
402
+ // 二进制拼接每个块摘要
403
+ let length = 5;
404
+ if (sections.header.sign) {
405
+ length += sections.header.sign.length;
575
406
  }
576
- static callCryptoSignFunction(buffer, prikey, certpem) {
577
- let signature = null;
578
- if (!Signer_1.default.getRemoteCryptoSignFunction()) {
579
- // 使用默认
580
- signature = Signer_1.default.defaultCryptoSignFunction(buffer, prikey);
581
- }
582
- else {
583
- // 使用外部:传递原文件内容、证书内容
584
- const remoteCryptoSignFunction = Signer_1.default.getRemoteCryptoSignFunction();
585
- signature = remoteCryptoSignFunction(buffer, certpem);
586
- }
587
- return signature;
407
+ if (sections.central.sign) {
408
+ length += sections.central.sign.length;
588
409
  }
589
- /**
590
- * 加签名文件
591
- * @param filehashs
592
- * @param prikey
593
- * @param certpem
594
- */
595
- static signFiles(filehashs, prikey, certpem) {
596
- const chunk = {
597
- len: 8,
598
- size: 4,
599
- digests: [],
600
- sign: null
601
- };
602
- // 生成hash块
603
- filehashs.forEach((item) => {
604
- // name hash
605
- const namehash = CRC32_1.default.digest(item.name);
606
- // 计算大小
607
- const sum = 6 + item.hash.length;
608
- const chk = Buffer.alloc(sum);
609
- let offset = 0;
610
- chk.writeInt32LE(namehash, offset);
611
- offset += 4;
612
- chk.writeInt16LE(item.hash.length, offset);
613
- offset += 2;
614
- item.hash.copy(chk, offset);
615
- offset += item.hash.length;
616
- chunk.digests.push(chk);
617
- chunk.size += sum;
618
- chunk.len += sum;
619
- });
620
- // 生成整体签名
621
- SignUtil.signDigestChunk(chunk, prikey, certpem);
622
- // 写入文件
623
- return SignUtil.saveDigestChunk(chunk);
410
+ if (sections.footer.sign) {
411
+ length += sections.footer.sign.length;
624
412
  }
625
- static signDigestChunk(chunk, prikey, certpem) {
626
- const buf = Buffer.alloc(chunk.size);
627
- let offset = 0;
628
- buf.writeInt32LE(0x0103, offset);
629
- offset += 4;
630
- chunk.digests.forEach((chk) => {
631
- chk.copy(buf, offset);
632
- offset += chk.length;
633
- });
634
- chunk.digests = buf.slice();
635
- // 生成签名
636
- const signature = SignUtil.callCryptoSignFunction(buf, prikey, certpem);
637
- chunk.sign = {
638
- len: 12 + signature.length,
639
- size: 8 + signature.length,
640
- id: 0x0103,
641
- data: signature
413
+ const wholeData = Buffer.alloc(length);
414
+ let offset = 0;
415
+ wholeData.writeInt8(0x5a, 0);
416
+ wholeData.writeInt32LE(3, 1);
417
+ offset += 5;
418
+ function writeBuffer(buf) {
419
+ buf.copy(wholeData, offset);
420
+ offset += buf.length;
421
+ }
422
+ sections.header.sign && writeBuffer(sections.header.sign);
423
+ sections.central.sign && writeBuffer(sections.central.sign);
424
+ sections.footer.sign && writeBuffer(sections.footer.sign);
425
+
426
+ // 计算整体摘要
427
+ const signer = _crypto.default.createHash('SHA256');
428
+ signer.update(wholeData);
429
+ const signature = signer.digest();
430
+
431
+ // 生成sign block, 计算block总长度, 向buf中考入数据
432
+ const signchunk = SignUtil.makeSignChunk(chunks.options, signature, privatekey, certificate);
433
+ chunks.signchunk = SignUtil.saveSignChunk(signchunk);
434
+ }
435
+ static makeSignChunk(options, sign, privatekey, certificate) {
436
+ // 提取公钥
437
+ const cert = Buffer.from(_Base.default.unarmor(certificate));
438
+ const c = new _jsrsasign.default.X509();
439
+ c.readCertPEM(certificate.toString());
440
+ const pubKey = _jsrsasign.default.KEYUTIL.getPEM(c.getPublicKey());
441
+ // 摘要块
442
+ const digestBuf = Buffer.alloc(sign.length + 12);
443
+ digestBuf.writeInt32LE(sign.length + 8, 0);
444
+ digestBuf.writeInt32LE(0x0103, 4);
445
+ digestBuf.writeInt32LE(sign.length, 8);
446
+ sign.copy(digestBuf, 12);
447
+ const digestBlock = {
448
+ len: digestBuf.length,
449
+ buffer: digestBuf
450
+ };
451
+
452
+ // 证书块
453
+ const certBuf = Buffer.alloc(cert.length + 4);
454
+ certBuf.writeInt32LE(cert.length, 0);
455
+ cert.copy(certBuf, 4);
456
+ const certBlock = {
457
+ len: certBuf.length,
458
+ buffer: certBuf
459
+ };
460
+
461
+ // 签名数据
462
+ const signdataBlock = {
463
+ len: 12,
464
+ digests: {
465
+ size: 0,
466
+ data: []
467
+ },
468
+ certs: {
469
+ size: 0,
470
+ data: []
471
+ },
472
+ additional: 0
473
+ };
474
+ signdataBlock.digests.data.push(digestBlock);
475
+ signdataBlock.digests.size += digestBlock.len;
476
+ signdataBlock.len += digestBlock.len;
477
+ signdataBlock.certs.data.push(certBlock);
478
+ signdataBlock.certs.size += certBlock.len;
479
+ signdataBlock.len += certBlock.len;
480
+
481
+ // 将public.pem转化为der
482
+ const pubbuf = Buffer.from(_Base.default.unarmor(pubKey));
483
+ const signBlock = {
484
+ len: 16 + pubbuf.length,
485
+ size: 12 + pubbuf.length,
486
+ signdata: {
487
+ size: 0,
488
+ buffer: null
489
+ },
490
+ signatures: {
491
+ size: 0,
492
+ data: []
493
+ },
494
+ pubkey: {
495
+ size: pubbuf.length,
496
+ buffer: pubbuf
497
+ }
498
+ };
499
+ signBlock.signdata.buffer = SignUtil.makeSignDataBuffer(signdataBlock);
500
+ signBlock.signdata.size = signdataBlock.len;
501
+ signBlock.size += signdataBlock.len;
502
+ signBlock.len += signdataBlock.len;
503
+
504
+ // 生成签名
505
+ const signature = SignUtil.callCryptoSignFunction(signBlock.signdata.buffer, privatekey, certificate);
506
+ const signatureBlock = {
507
+ len: signature.length + 12,
508
+ size: signature.length + 8,
509
+ id: 0x0103,
510
+ buffer: signature
511
+ };
512
+ signBlock.signatures.data.push(signatureBlock);
513
+ signBlock.signatures.size += signatureBlock.len;
514
+ signBlock.size += signatureBlock.len;
515
+ signBlock.len += signatureBlock.len;
516
+ const signBlocks = {
517
+ len: 4,
518
+ size: 0,
519
+ data: []
520
+ };
521
+ signBlocks.data.push(signBlock);
522
+ signBlocks.size += signBlock.len;
523
+ signBlocks.len += signBlock.len;
524
+
525
+ // 生成key-value
526
+ const kvBlock = {
527
+ len: signBlocks.len + 12,
528
+ size: signBlocks.len + 4,
529
+ id: 0x01000101,
530
+ value: signBlocks
531
+ };
532
+ const signchunk = {
533
+ len: 32,
534
+ size: 24,
535
+ data: []
536
+ };
537
+ signchunk.data.push(kvBlock);
538
+ signchunk.size += kvBlock.len;
539
+ signchunk.len += kvBlock.len;
540
+
541
+ // 添加文件列表hash kvblock
542
+ if (options.files) {
543
+ const filehashChunk = SignUtil.signFiles(options.files, privatekey, certificate);
544
+ if (filehashChunk) {
545
+ const filesignBlocks = {
546
+ len: 4,
547
+ size: 0,
548
+ data: []
549
+ };
550
+ filesignBlocks.data.push(filehashChunk);
551
+ filesignBlocks.size += filehashChunk.length;
552
+ filesignBlocks.len += filehashChunk.length;
553
+ const filekvBlock = {
554
+ len: filesignBlocks.len + 12,
555
+ size: filesignBlocks.len + 4,
556
+ id: 0x01000201,
557
+ value: filesignBlocks
642
558
  };
643
- chunk.len += chunk.sign.len;
559
+ signchunk.data.push(filekvBlock);
560
+ signchunk.size += filekvBlock.len;
561
+ signchunk.len += filekvBlock.len;
562
+ }
644
563
  }
645
- static saveDigestChunk(chunk) {
646
- // 创建新buffer
647
- const newBuffer = Buffer.alloc(chunk.len);
648
- let offset = 0;
649
- newBuffer.writeInt32LE(chunk.size, offset);
650
- offset += 4;
651
- // 文件hash列表
652
- chunk.digests.copy(newBuffer, offset);
653
- offset += chunk.digests.length;
654
- // 写入签名
655
- newBuffer.writeInt32LE(chunk.sign.size, offset);
656
- offset += 4;
657
- newBuffer.writeInt32LE(chunk.sign.id, offset);
658
- offset += 4;
659
- newBuffer.writeInt32LE(chunk.sign.data.length, offset);
660
- offset += 4;
661
- chunk.sign.data.copy(newBuffer, offset);
662
- offset += chunk.sign.data.length;
663
- return newBuffer;
564
+ return signchunk;
565
+ }
566
+ static makeSignDataBuffer(block) {
567
+ const buffer = Buffer.alloc(block.len);
568
+ let offset = 0;
569
+ buffer.writeInt32LE(block.digests.size, offset);
570
+ offset += 4;
571
+ block.digests.data.forEach(item => {
572
+ item.buffer.copy(buffer, offset);
573
+ offset += item.len;
574
+ });
575
+ buffer.writeInt32LE(block.certs.size, offset);
576
+ offset += 4;
577
+ block.certs.data.forEach(item => {
578
+ item.buffer.copy(buffer, offset);
579
+ offset += item.len;
580
+ });
581
+ buffer.writeInt32LE(block.additional, offset);
582
+ return buffer;
583
+ }
584
+ static callCryptoSignFunction(buffer, prikey, certpem) {
585
+ let signature = null;
586
+ if (!_Signer.default.getRemoteCryptoSignFunction()) {
587
+ // 使用默认
588
+ signature = _Signer.default.defaultCryptoSignFunction(buffer, prikey);
589
+ } else {
590
+ // 使用外部:传递原文件内容、证书内容
591
+ const remoteCryptoSignFunction = _Signer.default.getRemoteCryptoSignFunction();
592
+ signature = remoteCryptoSignFunction(buffer, certpem);
664
593
  }
665
- static saveSignChunk(signchunk) {
666
- const buffer = Buffer.alloc(signchunk.len);
667
- let offset = 0;
668
- // 大小
669
- buffer.writeInt32LE(signchunk.size, offset);
670
- offset += 4;
671
- buffer.writeInt32LE(0, offset);
672
- offset += 4;
673
- // key-value
674
- signchunk.data.forEach((kv) => {
675
- buffer.writeInt32LE(kv.size, offset);
676
- offset += 4;
677
- buffer.writeInt32LE(0, offset);
594
+ return signature;
595
+ }
596
+ /**
597
+ * 加签名文件
598
+ * @param filehashs
599
+ * @param prikey
600
+ * @param certpem
601
+ */
602
+ static signFiles(filehashs, prikey, certpem) {
603
+ const chunk = {
604
+ len: 8,
605
+ size: 4,
606
+ digests: [],
607
+ sign: null
608
+ };
609
+ // 生成hash块
610
+ filehashs.forEach(item => {
611
+ // name hash
612
+ const namehash = _CRC.default.digest(item.name);
613
+
614
+ // 计算大小
615
+ const sum = 6 + item.hash.length;
616
+ const chk = Buffer.alloc(sum);
617
+ let offset = 0;
618
+ chk.writeInt32LE(namehash, offset);
619
+ offset += 4;
620
+ chk.writeInt16LE(item.hash.length, offset);
621
+ offset += 2;
622
+ item.hash.copy(chk, offset);
623
+ offset += item.hash.length;
624
+ chunk.digests.push(chk);
625
+ chunk.size += sum;
626
+ chunk.len += sum;
627
+ });
628
+
629
+ // 生成整体签名
630
+ SignUtil.signDigestChunk(chunk, prikey, certpem);
631
+
632
+ // 写入文件
633
+ return SignUtil.saveDigestChunk(chunk);
634
+ }
635
+ static signDigestChunk(chunk, prikey, certpem) {
636
+ const buf = Buffer.alloc(chunk.size);
637
+ let offset = 0;
638
+ buf.writeInt32LE(0x0103, offset);
639
+ offset += 4;
640
+ chunk.digests.forEach(chk => {
641
+ chk.copy(buf, offset);
642
+ offset += chk.length;
643
+ });
644
+ chunk.digests = buf.slice();
645
+
646
+ // 生成签名
647
+ const signature = SignUtil.callCryptoSignFunction(buf, prikey, certpem);
648
+ chunk.sign = {
649
+ len: 12 + signature.length,
650
+ size: 8 + signature.length,
651
+ id: 0x0103,
652
+ data: signature
653
+ };
654
+ chunk.len += chunk.sign.len;
655
+ }
656
+ static saveDigestChunk(chunk) {
657
+ // 创建新buffer
658
+ const newBuffer = Buffer.alloc(chunk.len);
659
+ let offset = 0;
660
+ newBuffer.writeInt32LE(chunk.size, offset);
661
+ offset += 4;
662
+
663
+ // 文件hash列表
664
+ chunk.digests.copy(newBuffer, offset);
665
+ offset += chunk.digests.length;
666
+
667
+ // 写入签名
668
+ newBuffer.writeInt32LE(chunk.sign.size, offset);
669
+ offset += 4;
670
+ newBuffer.writeInt32LE(chunk.sign.id, offset);
671
+ offset += 4;
672
+ newBuffer.writeInt32LE(chunk.sign.data.length, offset);
673
+ offset += 4;
674
+ chunk.sign.data.copy(newBuffer, offset);
675
+ offset += chunk.sign.data.length;
676
+ return newBuffer;
677
+ }
678
+ static SigMagic = 'RPK Sig Block 42';
679
+ static saveSignChunk(signchunk) {
680
+ const buffer = Buffer.alloc(signchunk.len);
681
+ let offset = 0;
682
+
683
+ // 大小
684
+ buffer.writeInt32LE(signchunk.size, offset);
685
+ offset += 4;
686
+ buffer.writeInt32LE(0, offset);
687
+ offset += 4;
688
+
689
+ // key-value
690
+ signchunk.data.forEach(kv => {
691
+ buffer.writeInt32LE(kv.size, offset);
692
+ offset += 4;
693
+ buffer.writeInt32LE(0, offset);
694
+ offset += 4;
695
+ buffer.writeInt32LE(kv.id, offset);
696
+ offset += 4;
697
+
698
+ // value
699
+ buffer.writeInt32LE(kv.value.size, offset);
700
+ offset += 4;
701
+ if (kv.id === 0x01000101) {
702
+ // sign blocks
703
+ kv.value.data.forEach(block => {
704
+ buffer.writeInt32LE(block.size, offset);
705
+ offset += 4;
706
+
707
+ // signdata
708
+ buffer.writeInt32LE(block.signdata.size, offset);
709
+ offset += 4;
710
+ block.signdata.buffer.copy(buffer, offset);
711
+ offset += block.signdata.buffer.length;
712
+
713
+ // signature
714
+ buffer.writeInt32LE(block.signatures.size, offset);
715
+ offset += 4;
716
+ block.signatures.data.forEach(signature => {
717
+ buffer.writeInt32LE(signature.size, offset);
678
718
  offset += 4;
679
- buffer.writeInt32LE(kv.id, offset);
719
+ buffer.writeInt32LE(signature.id, offset);
680
720
  offset += 4;
681
- // value
682
- buffer.writeInt32LE(kv.value.size, offset);
721
+ buffer.writeInt32LE(signature.buffer.length, offset);
683
722
  offset += 4;
684
- if (kv.id === 0x01000101) {
685
- // sign blocks
686
- kv.value.data.forEach((block) => {
687
- buffer.writeInt32LE(block.size, offset);
688
- offset += 4;
689
- // signdata
690
- buffer.writeInt32LE(block.signdata.size, offset);
691
- offset += 4;
692
- block.signdata.buffer.copy(buffer, offset);
693
- offset += block.signdata.buffer.length;
694
- // signature
695
- buffer.writeInt32LE(block.signatures.size, offset);
696
- offset += 4;
697
- block.signatures.data.forEach((signature) => {
698
- buffer.writeInt32LE(signature.size, offset);
699
- offset += 4;
700
- buffer.writeInt32LE(signature.id, offset);
701
- offset += 4;
702
- buffer.writeInt32LE(signature.buffer.length, offset);
703
- offset += 4;
704
- signature.buffer.copy(buffer, offset);
705
- offset += signature.buffer.length;
706
- });
707
- // pubkey
708
- buffer.writeInt32LE(block.pubkey.size, offset);
709
- offset += 4;
710
- block.pubkey.buffer.copy(buffer, offset);
711
- offset += block.pubkey.buffer.length;
712
- });
713
- }
714
- else if (kv.id === 0x01000201) {
715
- // files blocks
716
- kv.value.data.forEach((block) => {
717
- block.copy(buffer, offset);
718
- offset += block.length;
719
- });
720
- }
723
+ signature.buffer.copy(buffer, offset);
724
+ offset += signature.buffer.length;
725
+ });
726
+
727
+ // pubkey
728
+ buffer.writeInt32LE(block.pubkey.size, offset);
729
+ offset += 4;
730
+ block.pubkey.buffer.copy(buffer, offset);
731
+ offset += block.pubkey.buffer.length;
721
732
  });
722
- // 大小
723
- buffer.writeInt32LE(signchunk.size, offset);
724
- offset += 4;
725
- buffer.writeInt32LE(0, offset);
726
- offset += 4;
727
- // 魔法值
728
- const magic = Buffer.from(SignUtil.SigMagic);
729
- magic.copy(buffer, offset);
730
- return buffer;
731
- }
732
- static saveChunk(buf, chunks) {
733
- // 创建新buffer
734
- const newBuffer = Buffer.alloc(buf.length + chunks.signchunk.length);
735
- let offset = 0;
736
- const sections = chunks.sections;
737
- // 拷贝header
738
- buf.copy(newBuffer, offset, sections.header.startIndex, sections.header.startIndex + sections.header.len);
739
- offset += sections.header.len;
740
- // 拷贝signblock
741
- chunks.signchunk.copy(newBuffer, offset);
742
- offset += chunks.signchunk.length;
743
- // 拷贝central
744
- buf.copy(newBuffer, offset, sections.central.startIndex, sections.central.startIndex + sections.central.len);
745
- offset += sections.central.len;
746
- // 修改eocd
747
- buf.writeInt32LE(sections.central.startIndex + chunks.signchunk.length, sections.footer.startIndex + 16);
748
- // 拷贝eocd
749
- buf.copy(newBuffer, offset, sections.footer.startIndex, sections.footer.startIndex + sections.footer.len);
750
- offset += sections.footer.len;
751
- return newBuffer;
752
- }
753
- /**
754
- * 过滤掉文件夹和META文件
755
- * @param item
756
- * @returns
757
- */
758
- static fileFilter(item) {
759
- const path = item.path;
760
- return !path.endsWith('/') && path !== ZipUtil_1.default.CERT_PATH;
761
- }
733
+ } else if (kv.id === 0x01000201) {
734
+ // files blocks
735
+ kv.value.data.forEach(block => {
736
+ block.copy(buffer, offset);
737
+ offset += block.length;
738
+ });
739
+ }
740
+ });
741
+
742
+ // 大小
743
+ buffer.writeInt32LE(signchunk.size, offset);
744
+ offset += 4;
745
+ buffer.writeInt32LE(0, offset);
746
+ offset += 4;
747
+
748
+ // 魔法值
749
+ const magic = Buffer.from(SignUtil.SigMagic);
750
+ magic.copy(buffer, offset);
751
+ return buffer;
752
+ }
753
+ static saveChunk(buf, chunks) {
754
+ // 创建新buffer
755
+ const newBuffer = Buffer.alloc(buf.length + chunks.signchunk.length);
756
+ let offset = 0;
757
+ const sections = chunks.sections;
758
+
759
+ // 拷贝header
760
+ buf.copy(newBuffer, offset, sections.header.startIndex, sections.header.startIndex + sections.header.len);
761
+ offset += sections.header.len;
762
+
763
+ // 拷贝signblock
764
+ chunks.signchunk.copy(newBuffer, offset);
765
+ offset += chunks.signchunk.length;
766
+
767
+ // 拷贝central
768
+ buf.copy(newBuffer, offset, sections.central.startIndex, sections.central.startIndex + sections.central.len);
769
+ offset += sections.central.len;
770
+
771
+ // 修改eocd
772
+ buf.writeInt32LE(sections.central.startIndex + chunks.signchunk.length, sections.footer.startIndex + 16);
773
+ // 拷贝eocd
774
+ buf.copy(newBuffer, offset, sections.footer.startIndex, sections.footer.startIndex + sections.footer.len);
775
+ offset += sections.footer.len;
776
+ return newBuffer;
777
+ }
778
+ /**
779
+ * 过滤掉文件夹和META文件
780
+ * @param item
781
+ * @returns
782
+ */
783
+ static fileFilter(item) {
784
+ const path = item.path;
785
+ return !path.endsWith('/') && path !== _ZipUtil.default.CERT_PATH;
786
+ }
762
787
  }
763
- SignUtil.SigMagic = 'RPK Sig Block 42';
764
- exports.default = SignUtil;
788
+ var _default = exports.default = SignUtil;