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