@ysgroup/core 0.1.12 → 0.1.14

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/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@ysgroup/core",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
7
+ "dependencies": {
8
+ "@noble/ciphers": "2.4.0",
9
+ "@noble/curves": "2.4.0",
10
+ "@noble/hashes": "2.4.0"
11
+ },
7
12
  "peerDependencies": {
8
13
  "pinia": ">=2.2",
9
14
  "vue": ">=3.5"
package/src/password.ts CHANGED
@@ -1,4 +1,11 @@
1
- /* 登录口令密封:X25519 临时密钥 + HKDF-SHA256 + AES-256-GCM,与 Auth/ys_base 对齐。 */
1
+ /* 登录口令密封:X25519 + HKDF-SHA256 + AES-256-GCM
2
+ 使用 @noble/* 纯 JS,不依赖 Web Crypto SubtleCrypto。
3
+ HTTP(非安全上下文)与 HTTPS 同一路径,信封格式与 Auth/ys_base 对齐。 */
4
+
5
+ import { gcm } from "@noble/ciphers/aes.js";
6
+ import { x25519 } from "@noble/curves/ed25519.js";
7
+ import { hkdf } from "@noble/hashes/hkdf.js";
8
+ import { sha256 } from "@noble/hashes/sha2.js";
2
9
 
3
10
  export interface PasswordWrap {
4
11
  password_wrap: string;
@@ -77,76 +84,23 @@ export async function sealPassword(
77
84
  const recipientRaw = b64uDecode(publicKeyB64);
78
85
  if (recipientRaw.byteLength !== 32) throw new Error("登录公钥长度无效");
79
86
 
80
- const ephemeral = (await crypto.subtle.generateKey({ name: "X25519" }, true, [
81
- "deriveBits",
82
- ])) as CryptoKeyPair;
83
- const recipient = await crypto.subtle.importKey(
84
- "raw",
85
- asArrayBuffer(recipientRaw),
86
- { name: "X25519" },
87
- false,
88
- [],
89
- );
90
- const shared = new Uint8Array(
91
- await crypto.subtle.deriveBits(
92
- { name: "X25519", public: recipient },
93
- ephemeral.privateKey,
94
- 256,
95
- ),
96
- );
97
- const hkdfKey = await crypto.subtle.importKey(
98
- "raw",
99
- asArrayBuffer(shared),
100
- "HKDF",
101
- false,
102
- ["deriveBits"],
103
- );
104
- const aesRaw = await crypto.subtle.deriveBits(
105
- {
106
- name: "HKDF",
107
- hash: "SHA-256",
108
- salt: asArrayBuffer(SALT),
109
- info: asArrayBuffer(INFO),
110
- },
111
- hkdfKey,
112
- 256,
113
- );
114
- const aesKey = await crypto.subtle.importKey(
115
- "raw",
116
- aesRaw,
117
- { name: "AES-GCM" },
118
- false,
119
- ["encrypt"],
120
- );
87
+ const ephemeralSecret = x25519.utils.randomSecretKey();
88
+ const ephemeralPublic = x25519.getPublicKey(ephemeralSecret);
89
+ const shared = x25519.getSharedSecret(ephemeralSecret, recipientRaw);
90
+ const aesRaw = hkdf(sha256, shared, SALT, INFO, 32);
121
91
  const aad = new TextEncoder().encode(`${PREFIX}${kid}`);
122
- const packedCt = new Uint8Array(
123
- await crypto.subtle.encrypt(
124
- {
125
- name: "AES-GCM",
126
- iv: asArrayBuffer(NONCE),
127
- additionalData: aad,
128
- tagLength: 128,
129
- },
130
- aesKey,
131
- new TextEncoder().encode(plaintext),
132
- ),
92
+ const packedCt = gcm(aesRaw, NONCE, aad).encrypt(
93
+ new TextEncoder().encode(plaintext),
133
94
  );
134
- const ephPk = new Uint8Array(
135
- await crypto.subtle.exportKey("raw", ephemeral.publicKey),
95
+ const packed = new Uint8Array(
96
+ ephemeralPublic.byteLength + packedCt.byteLength,
136
97
  );
137
- const packed = new Uint8Array(ephPk.byteLength + packedCt.byteLength);
138
- packed.set(ephPk, 0);
139
- packed.set(packedCt, ephPk.byteLength);
98
+ packed.set(ephemeralPublic, 0);
99
+ packed.set(packedCt, ephemeralPublic.byteLength);
100
+ ephemeralSecret.fill(0);
140
101
  return `${PREFIX}${kid}.${b64uEncode(packed)}`;
141
102
  }
142
103
 
143
- function asArrayBuffer(bytes: Uint8Array): ArrayBuffer {
144
- return bytes.buffer.slice(
145
- bytes.byteOffset,
146
- bytes.byteOffset + bytes.byteLength,
147
- ) as ArrayBuffer;
148
- }
149
-
150
104
  function b64uEncode(raw: Uint8Array): string {
151
105
  let bin = "";
152
106
  for (const byte of raw) bin += String.fromCharCode(byte);
package/src/store.ts CHANGED
@@ -101,17 +101,12 @@ export const useYsStore = defineStore("ys", () => {
101
101
  return "登录状态已失效,请重新登录。";
102
102
  }
103
103
 
104
- async function login(
105
- username: string,
106
- password: string,
107
- otp = "",
108
- ): Promise<void> {
104
+ async function login(username: string, password: string): Promise<void> {
109
105
  if (!ws) throw new Error("未连接");
110
106
  sessionMessage.value = "";
111
107
  const result = (await ws.call("login", {
112
108
  username,
113
109
  password: await sealLoginPassword(password),
114
- otp,
115
110
  app_name: appName.value,
116
111
  user_agent: navigator.userAgent,
117
112
  })) as LoginResult;