SHA256
Промежуточный коммит: состояние до нормальной Solana-first регистрации
This commit is contained in:
@@ -86,14 +86,29 @@ async function derivePasswordSeedArgon2id({ login, password, suffix }) {
|
||||
const salt = await makeArgon2Salt(normalizedLogin, normalizedSuffix);
|
||||
const passBytes = utf8Bytes(`${normalizedLogin}\n${normalizedPassword}`);
|
||||
const out = await argon2idAsync(passBytes, salt, {
|
||||
t: 3,
|
||||
m: 262144,
|
||||
t: 2,
|
||||
m: 65536,
|
||||
p: 1,
|
||||
dkLen: 32,
|
||||
});
|
||||
return new Uint8Array(out);
|
||||
}
|
||||
|
||||
async function deriveMasterSecretArgon2id({ login, password, onProgress }) {
|
||||
const normalizedLogin = normalizeLoginForKdf(login);
|
||||
const normalizedPassword = String(password ?? '');
|
||||
const salt = await makeArgon2Salt(normalizedLogin, 'master.secret');
|
||||
const passBytes = utf8Bytes(`${normalizedLogin}\n${normalizedPassword}`);
|
||||
const out = await argon2idAsync(passBytes, salt, {
|
||||
t: 2,
|
||||
m: 65536,
|
||||
p: 1,
|
||||
dkLen: 32,
|
||||
onProgress,
|
||||
});
|
||||
return new Uint8Array(out);
|
||||
}
|
||||
|
||||
function ed25519Pkcs8FromSeed(seed32) {
|
||||
if (seed32.length !== 32) {
|
||||
throw new Error('Для Ed25519 нужен seed длиной 32 байта');
|
||||
@@ -131,6 +146,43 @@ export async function deriveEd25519FromPassword(password, suffix, options = {})
|
||||
};
|
||||
}
|
||||
|
||||
export async function deriveMasterSecretFromPassword(password, options = {}) {
|
||||
const normalizedPassword = String(password ?? '');
|
||||
const normalizedLogin = String(options?.login ?? '');
|
||||
const onProgress = typeof options?.onProgress === 'function' ? options.onProgress : undefined;
|
||||
if (normalizedPassword.length === 0) {
|
||||
const legacy = await derivePasswordSeed(normalizedPassword, 'master.secret');
|
||||
if (onProgress) onProgress(1);
|
||||
return legacy;
|
||||
}
|
||||
return deriveMasterSecretArgon2id({
|
||||
login: normalizedLogin,
|
||||
password: normalizedPassword,
|
||||
onProgress,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deriveEd25519FromMasterSecret(masterSecret32, suffix) {
|
||||
const secretBytes = masterSecret32 instanceof Uint8Array
|
||||
? masterSecret32
|
||||
: new Uint8Array(masterSecret32 || []);
|
||||
if (secretBytes.length !== 32) {
|
||||
throw new Error('Master secret должен быть длиной 32 байта');
|
||||
}
|
||||
const material = `${bytesToBase64(secretBytes)}|${String(suffix || '')}`;
|
||||
const seed = await sha256Text(material);
|
||||
const pkcs8 = ed25519Pkcs8FromSeed(seed);
|
||||
const subtle = getSubtleApi();
|
||||
const privateKey = await subtle.importKey('pkcs8', pkcs8, { name: 'Ed25519' }, true, ['sign']);
|
||||
const jwk = await subtle.exportKey('jwk', privateKey);
|
||||
if (!jwk.x) throw new Error('Не удалось получить публичный ключ Ed25519');
|
||||
return {
|
||||
privateKey,
|
||||
publicKeyB64: bytesToBase64(base64ToBytes(base64UrlToBase64(jwk.x))),
|
||||
privatePkcs8B64: bytesToBase64(pkcs8),
|
||||
};
|
||||
}
|
||||
|
||||
export async function deriveAesKeyFromStoragePwd(storagePwd, saltBytes) {
|
||||
const subtle = getSubtleApi();
|
||||
const baseKey = await subtle.importKey(
|
||||
|
||||
Reference in New Issue
Block a user