@h-ai/crypto 1.0.0-beta.7 → 1.0.0-beta.8
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.en.md +2 -0
- package/README.ja.md +2 -0
- package/README.md +2 -0
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.en.md
CHANGED
|
@@ -156,6 +156,8 @@ if (hashed.success) {
|
|
|
156
156
|
|
|
157
157
|
#### Transport encryption (crypto.transport)
|
|
158
158
|
|
|
159
|
+
Transport client `destroy()` invalidates and aborts an in-flight handshake; late results cannot restore keys or overwrite the next handshake. It clears local state; server registry entries retain their own expiry.
|
|
160
|
+
|
|
159
161
|
See the [Transport v2 wire protocol](TRANSPORT-PROTOCOL.md) for canonical encoding, verification order and replay persistence.
|
|
160
162
|
|
|
161
163
|
The `crypto.transport` namespace provides transport encryption, allowing `@h-ai/serv`, `@h-ai/kit`, and `@h-ai/api-client` to share protocol constants and payload formats.
|
package/README.ja.md
CHANGED
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
### セキュリティに関する注意
|
|
23
23
|
|
|
24
|
+
伝送クライアントの `destroy()` は進行中のハンドシェイクを無効化して中断し、遅延結果による鍵の復活や次回ハンドシェイクの上書きを防ぎます。サーバー registry は自身の期限で回収します。
|
|
25
|
+
|
|
24
26
|
- **SM4 の既定の暗号化結果は構造化された暗号文**:`crypto.symmetric.encrypt(data, key)` は既定で CBC + ランダム IV を使用し、`{ mode, ciphertext, iv, encoding }` を返します。復号時はこのオブジェクトを `crypto.symmetric.decrypt(payload, key)` に渡します。
|
|
25
27
|
- **SM4 にはランダムな鍵を使用してください**:`crypto.symmetric.generateKey()` で鍵を生成します。このモジュールはパスワードから暗号鍵を導出する KDF を提供しません。パスワードの保存にはサーバー専用の `crypto.password.hash(password)` を使用し、パスワードやそのハッシュを直接 SM4 の鍵にしないでください。
|
|
26
28
|
- **IV は毎回一意にしてください**:同じ鍵で IV を再利用してはいけません。既定の CBC または `encryptWithIV()` による毎回の自動生成を推奨します。IV は暗号文と一緒に送信・保存します(公開可能で、秘密にする必要はありません)。
|
package/README.md
CHANGED
|
@@ -156,6 +156,8 @@ if (hashed.success) {
|
|
|
156
156
|
|
|
157
157
|
#### 传输加密(crypto.transport)
|
|
158
158
|
|
|
159
|
+
传输客户端 `destroy()` 使在途握手失效并取消网络等待;迟到结果不能恢复密钥或覆盖下一次握手。它只清理本地会话,服务端 registry 仍按自己的租约回收。
|
|
160
|
+
|
|
159
161
|
规范编码、验证顺序与 nonce 持久化要求见 [Transport v2 协议](TRANSPORT-PROTOCOL.md)。
|
|
160
162
|
|
|
161
163
|
传输加密统一通过 `crypto.transport` 命名空间提供,供 `@h-ai/serv`、`@h-ai/kit` 与 `@h-ai/api-client` 复用同一套协议常量和载荷格式。
|
package/dist/index.js
CHANGED
|
@@ -1125,7 +1125,9 @@ function createTransportClient(options) {
|
|
|
1125
1125
|
let serverKeyId = null;
|
|
1126
1126
|
let clientId = null;
|
|
1127
1127
|
let initPromise = null;
|
|
1128
|
-
|
|
1128
|
+
let generation = 0;
|
|
1129
|
+
let handshakeController;
|
|
1130
|
+
async function doInit(attemptGeneration) {
|
|
1129
1131
|
const kpResult = options.crypto.asymmetric.generateKeyPair();
|
|
1130
1132
|
if (!kpResult.success)
|
|
1131
1133
|
return err(HaiCommonError.INTERNAL_ERROR, cryptoM("crypto_transportClientKeyGenerateFailed"), kpResult.error);
|
|
@@ -1133,6 +1135,7 @@ function createTransportClient(options) {
|
|
|
1133
1135
|
if (new TextEncoder().encode(localKeyPair.publicKey).byteLength > TRANSPORT_BODY_LIMITS.publicKeyBytes)
|
|
1134
1136
|
return err(HaiCommonError.INTERNAL_ERROR, cryptoM("crypto_transportClientKeyGenerateFailed"));
|
|
1135
1137
|
const controller = new AbortController();
|
|
1138
|
+
handshakeController = controller;
|
|
1136
1139
|
const timeout = setTimeout(() => controller.abort(new DOMException("Key exchange timed out", "TimeoutError")), 3e4);
|
|
1137
1140
|
try {
|
|
1138
1141
|
let response;
|
|
@@ -1169,6 +1172,8 @@ function createTransportClient(options) {
|
|
|
1169
1172
|
} catch {
|
|
1170
1173
|
return err(HaiCommonError.INTERNAL_ERROR, cryptoM("crypto_transportBodyLimitInvalid"));
|
|
1171
1174
|
}
|
|
1175
|
+
if (attemptGeneration !== generation || controller.signal.aborted)
|
|
1176
|
+
return err(HaiCommonError.INTERNAL_ERROR, cryptoM("crypto_transportClientNotInitialized"));
|
|
1172
1177
|
keyPair = localKeyPair;
|
|
1173
1178
|
serverPublicKey = body.serverPublicKey;
|
|
1174
1179
|
serverKeyId = body.serverKeyId;
|
|
@@ -1176,17 +1181,20 @@ function createTransportClient(options) {
|
|
|
1176
1181
|
return ok(void 0);
|
|
1177
1182
|
} finally {
|
|
1178
1183
|
clearTimeout(timeout);
|
|
1184
|
+
if (handshakeController === controller)
|
|
1185
|
+
handshakeController = void 0;
|
|
1179
1186
|
}
|
|
1180
1187
|
}
|
|
1181
1188
|
async function ensureReady() {
|
|
1182
1189
|
if (clientId && serverPublicKey)
|
|
1183
1190
|
return ok(void 0);
|
|
1184
1191
|
if (!initPromise) {
|
|
1185
|
-
|
|
1186
|
-
if (!result.success)
|
|
1192
|
+
const pending = doInit(generation).then((result) => {
|
|
1193
|
+
if (!result.success && initPromise === pending)
|
|
1187
1194
|
initPromise = null;
|
|
1188
1195
|
return result;
|
|
1189
1196
|
});
|
|
1197
|
+
initPromise = pending;
|
|
1190
1198
|
}
|
|
1191
1199
|
return initPromise;
|
|
1192
1200
|
}
|
|
@@ -1360,6 +1368,9 @@ function createTransportClient(options) {
|
|
|
1360
1368
|
encryptedFetch,
|
|
1361
1369
|
ready: () => clientId !== null && serverPublicKey !== null,
|
|
1362
1370
|
destroy() {
|
|
1371
|
+
generation++;
|
|
1372
|
+
handshakeController?.abort();
|
|
1373
|
+
handshakeController = void 0;
|
|
1363
1374
|
keyPair = null;
|
|
1364
1375
|
serverPublicKey = null;
|
|
1365
1376
|
serverKeyId = null;
|