sm-crypto-wasm 0.1.0 → 0.1.1
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/dist/sm2/index.js +39 -25
- package/dist/sm4/index.js +2 -2
- package/dist/sm9/index.js +8 -4
- package/dist/sm9/sm9.wasm +0 -0
- package/package.json +1 -1
package/dist/sm2/index.js
CHANGED
|
@@ -65,6 +65,24 @@ function getModule() {
|
|
|
65
65
|
throw new Error('sm2: 未初始化,请先 `await ensureLoaded()`。');
|
|
66
66
|
return mod;
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* 现取 WASM memory 视图。
|
|
70
|
+
*
|
|
71
|
+
* **每次都用**,绝不在多次 `alloc` / wasm 调用之间缓存 `new Uint8Array(memory.buffer)`:
|
|
72
|
+
* 任何一次分配都可能让 WASM 堆增长(`memory.grow`),旧的 ArrayBuffer 会被 detach,
|
|
73
|
+
* 复用旧视图会抛 `TypeError: Cannot perform Construct on a detached ArrayBuffer`。
|
|
74
|
+
*/
|
|
75
|
+
function memView() {
|
|
76
|
+
return new Uint8Array(getModule().memory.buffer);
|
|
77
|
+
}
|
|
78
|
+
/** 写入字节到 WASM 内存(现取视图)。 */
|
|
79
|
+
function putBytes(b, ptr) {
|
|
80
|
+
memView().set(b, ptr);
|
|
81
|
+
}
|
|
82
|
+
/** 读出 WASM 内存的拷贝(现取视图后 slice,不向上层交出会失效的视图)。 */
|
|
83
|
+
function readBytes(ptr, len) {
|
|
84
|
+
return new Uint8Array(getModule().memory.buffer, ptr, len).slice();
|
|
85
|
+
}
|
|
68
86
|
/**
|
|
69
87
|
* 从私钥派生公钥。
|
|
70
88
|
*
|
|
@@ -80,13 +98,13 @@ export function getPublicKey(privateKey) {
|
|
|
80
98
|
* `getPublicKey` 与缓存未命中时的 `derivePublicKeyBytes` 都走这里。
|
|
81
99
|
*/
|
|
82
100
|
function derivePublicKeyRaw(d) {
|
|
83
|
-
const { exports
|
|
101
|
+
const { exports } = getModule();
|
|
84
102
|
const dp = exports.alloc(32);
|
|
85
103
|
const op = exports.alloc(64);
|
|
86
104
|
try {
|
|
87
|
-
|
|
105
|
+
putBytes(d, dp);
|
|
88
106
|
exports.publicKeyOut(dp, op);
|
|
89
|
-
return
|
|
107
|
+
return readBytes(op, 64);
|
|
90
108
|
}
|
|
91
109
|
finally {
|
|
92
110
|
exports.freeAll();
|
|
@@ -209,7 +227,6 @@ export function sign(privateKey, message) {
|
|
|
209
227
|
const m = toBytes(message, 'message');
|
|
210
228
|
const pub = derivePublicKeyBytes(d);
|
|
211
229
|
const { exports } = getModule();
|
|
212
|
-
const mem = new Uint8Array(getModule().memory.buffer);
|
|
213
230
|
const dp = exports.alloc(32);
|
|
214
231
|
const pxp = exports.alloc(32);
|
|
215
232
|
const pyp = exports.alloc(32);
|
|
@@ -217,17 +234,17 @@ export function sign(privateKey, message) {
|
|
|
217
234
|
const kp = exports.alloc(32);
|
|
218
235
|
const op = exports.alloc(64);
|
|
219
236
|
try {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
237
|
+
putBytes(d, dp);
|
|
238
|
+
putBytes(pub.subarray(0, 32), pxp);
|
|
239
|
+
putBytes(pub.subarray(32, 64), pyp);
|
|
240
|
+
putBytes(m, mp);
|
|
224
241
|
// 最多重试几次 k(极小概率 r/s 为 0 或 r+k==n)。
|
|
225
242
|
for (let attempt = 0; attempt < 16; attempt++) {
|
|
226
243
|
const k = randomK();
|
|
227
|
-
|
|
244
|
+
putBytes(k, kp);
|
|
228
245
|
const rc = exports.signOut(dp, pxp, pyp, mp, m.length, kp, op);
|
|
229
246
|
if (rc === 0) {
|
|
230
|
-
return fromBytes(
|
|
247
|
+
return fromBytes(readBytes(op, 64), 'hex');
|
|
231
248
|
}
|
|
232
249
|
}
|
|
233
250
|
throw new Error('sm2.sign: failed to produce a valid signature after retries');
|
|
@@ -251,16 +268,15 @@ export function verify(publicKey, message, signature) {
|
|
|
251
268
|
if (sig.length !== 64)
|
|
252
269
|
throw new InvalidCiphertextError('sm2: signature must be 64 bytes');
|
|
253
270
|
const { exports } = getModule();
|
|
254
|
-
const mem = new Uint8Array(getModule().memory.buffer);
|
|
255
271
|
const pxp = exports.alloc(32);
|
|
256
272
|
const pyp = exports.alloc(32);
|
|
257
273
|
const mp = exports.alloc(m.length);
|
|
258
274
|
const sigp = exports.alloc(64);
|
|
259
275
|
try {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
276
|
+
putBytes(x, pxp);
|
|
277
|
+
putBytes(y, pyp);
|
|
278
|
+
putBytes(m, mp);
|
|
279
|
+
putBytes(sig, sigp);
|
|
264
280
|
return exports.verifyOut(pxp, pyp, mp, m.length, sigp) === 1;
|
|
265
281
|
}
|
|
266
282
|
finally {
|
|
@@ -286,21 +302,20 @@ export function encrypt(publicKey, message, opts = {}) {
|
|
|
286
302
|
}
|
|
287
303
|
const m = toBytes(message, 'message');
|
|
288
304
|
const { exports } = getModule();
|
|
289
|
-
const mem = new Uint8Array(getModule().memory.buffer);
|
|
290
305
|
const pxp = exports.alloc(32);
|
|
291
306
|
const pyp = exports.alloc(32);
|
|
292
307
|
const mp = exports.alloc(m.length);
|
|
293
308
|
const kp = exports.alloc(32);
|
|
294
309
|
const ctp = exports.alloc(97 + m.length);
|
|
295
310
|
try {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
311
|
+
putBytes(x, pxp);
|
|
312
|
+
putBytes(y, pyp);
|
|
313
|
+
putBytes(m, mp);
|
|
299
314
|
for (let attempt = 0; attempt < 16; attempt++) {
|
|
300
|
-
|
|
315
|
+
putBytes(randomK(), kp);
|
|
301
316
|
const rc = exports.encryptOut(pxp, pyp, mp, m.length, kp, ctp);
|
|
302
317
|
if (rc === 1) {
|
|
303
|
-
const raw =
|
|
318
|
+
const raw = readBytes(ctp, 97 + m.length);
|
|
304
319
|
return fromBytes(format === 'C1C2C3' ? c1c3c2ToC1c2c3(raw) : raw, 'hex');
|
|
305
320
|
}
|
|
306
321
|
}
|
|
@@ -354,18 +369,17 @@ function decryptUnsafe(privateKey, ciphertext, opts) {
|
|
|
354
369
|
/** 按 C1C3C2 布局解密(wasm 侧约定的布局)。 */
|
|
355
370
|
function decryptRaw(d, ct) {
|
|
356
371
|
const { exports } = getModule();
|
|
357
|
-
const mem = new Uint8Array(getModule().memory.buffer);
|
|
358
372
|
const dp = exports.alloc(32);
|
|
359
373
|
const ctp = exports.alloc(ct.length);
|
|
360
374
|
const outLen = ct.length - 97;
|
|
361
375
|
const ptp = exports.alloc(outLen === 0 ? 1 : outLen);
|
|
362
376
|
try {
|
|
363
|
-
|
|
364
|
-
|
|
377
|
+
putBytes(d, dp);
|
|
378
|
+
putBytes(ct, ctp);
|
|
365
379
|
const rc = exports.decryptOut(dp, ctp, ct.length, ptp);
|
|
366
380
|
if (rc !== 1)
|
|
367
381
|
throw new DecryptionError('sm2.decrypt: C3 verification failed');
|
|
368
|
-
return fromBytes(
|
|
382
|
+
return fromBytes(readBytes(ptp, outLen), 'hex');
|
|
369
383
|
}
|
|
370
384
|
finally {
|
|
371
385
|
exports.freeAll();
|
package/dist/sm4/index.js
CHANGED
|
@@ -34,7 +34,7 @@ function withBuffers(key, data, outLen, fn) {
|
|
|
34
34
|
const mem = new Uint8Array(memory.buffer);
|
|
35
35
|
mem.set(key, keyPtr);
|
|
36
36
|
mem.set(data, inPtr);
|
|
37
|
-
return fn(keyPtr, inPtr, outPtr
|
|
37
|
+
return fn(keyPtr, inPtr, outPtr);
|
|
38
38
|
}
|
|
39
39
|
finally {
|
|
40
40
|
exports.freeAll();
|
|
@@ -244,7 +244,7 @@ function withGcmBuffers(k, v, a, data, fn) {
|
|
|
244
244
|
mem.set(a, aadPtr);
|
|
245
245
|
if (data.length !== 0)
|
|
246
246
|
mem.set(data, inPtr);
|
|
247
|
-
return fn({ keyPtr, ivPtr, aadPtr, inPtr, outPtr, tagPtr }
|
|
247
|
+
return fn({ keyPtr, ivPtr, aadPtr, inPtr, outPtr, tagPtr });
|
|
248
248
|
}
|
|
249
249
|
finally {
|
|
250
250
|
exports.freeAll();
|
package/dist/sm9/index.js
CHANGED
|
@@ -354,17 +354,21 @@ export function encrypt(publicKey, id, msg, r) {
|
|
|
354
354
|
const idP = exports.alloc(idB.length);
|
|
355
355
|
const msgP = exports.alloc(msgB.length);
|
|
356
356
|
const rP = exports.alloc(32);
|
|
357
|
-
|
|
357
|
+
// 密文布局 C1(65) || C3(32) || C2(|msg|),长度随明文增长 —— 按实际长度分配,
|
|
358
|
+
// 并把容量一并交给 wasm 侧校验。曾硬编码 alloc(4096):明文超过 3999 字节时
|
|
359
|
+
// sm9Encrypt 会写越界、破坏 GC 堆(几轮后 RuntimeError: memory access out of bounds)。
|
|
360
|
+
const ctCap = 65 + 32 + msgB.length;
|
|
361
|
+
const ctP = exports.alloc(ctCap);
|
|
358
362
|
try {
|
|
359
363
|
putBytes(key.bytes, keyP);
|
|
360
364
|
putBytes(idB, idP);
|
|
361
365
|
putBytes(msgB, msgP);
|
|
362
366
|
putBytes(rB, rP);
|
|
363
367
|
const ctLen = key.kind === 'public'
|
|
364
|
-
? exports.sm9EncryptPubOut(keyP, idP, idB.length, msgP, msgB.length, rP, ctP)
|
|
365
|
-
: exports.sm9EncryptOut(keyP, idP, idB.length, msgP, msgB.length, rP, ctP);
|
|
368
|
+
? exports.sm9EncryptPubOut(keyP, idP, idB.length, msgP, msgB.length, rP, ctP, ctCap)
|
|
369
|
+
: exports.sm9EncryptOut(keyP, idP, idB.length, msgP, msgB.length, rP, ctP, ctCap);
|
|
366
370
|
if (ctLen < 0)
|
|
367
|
-
throw new Error('sm9: encrypt
|
|
371
|
+
throw new Error('sm9: encrypt 失败(密文缓冲容量不足)');
|
|
368
372
|
return readHex(ctP, ctLen);
|
|
369
373
|
}
|
|
370
374
|
finally {
|
package/dist/sm9/sm9.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sm-crypto-wasm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "国密 SM2/SM3/SM4/SM9/ZUC 的 WASM 实现,Node 18+ 与现代浏览器均可使用,按算法分包懒加载。",
|
|
5
5
|
"description:en": "SM2/SM3/SM4/SM9/ZUC (China crypto) implemented in AssemblyScript -> WASM. Node 18+ & modern browsers, per-algorithm lazy loading.",
|
|
6
6
|
"license": "Apache-2.0",
|