Новый протокол Solana PDA 1.2

This commit is contained in:
AidarKC
2026-09-26 11:01:14 +03:00
parent 6e5b57fd7c
commit c997057a37
47 changed files with 2392 additions and 4480 deletions
+3
View File
@@ -544,6 +544,9 @@ export function render({navigate, chrome}) {
if (operationBusy) return;
const normalizedList = uniqueLogins(nextLogins);
if (normalizedList.length > 1) {
throw new Error('PDA 1.2 поддерживает только один сервер доступа.');
}
setOperationBusy(true);
target.textContent = String(inFlightText || 'Обновляем сервер доступа...');
let signingMaterial = null;
+1 -1
View File
@@ -333,7 +333,7 @@ export function render({ navigate }) {
const subtitle = document.createElement('p');
subtitle.className = 'meta-muted';
subtitle.textContent = 'Процесс запускается сразу: из этого секрета будут вычислены recovery key, root key, blockchain key и client key.';
subtitle.textContent = 'Процесс запускается сразу: из этого секрета будут вычислены root/recovery key, blockchain key и client key.';
const details = document.createElement('p');
details.className = 'meta-muted';
@@ -109,31 +109,17 @@ export function render({ navigate }) {
}
card.append(makeSecretField({ label: 'Главный секрет (master secret, base58, 32 байта)', value: secretB58 }));
// Recovery key
const recoverySep = document.createElement('p');
recoverySep.className = 'field-label';
recoverySep.textContent = 'Recovery key';
card.append(recoverySep);
card.append(makePublicField({
label: 'Recovery — публичный (base58)',
value: bytesToBase58(base64ToBytes(keyBundle.recoveryPair.publicKeyB64)),
}));
card.append(makeSecretField({
label: 'Recovery — приватный (seed base58, 32 байта)',
value: bytesToBase58(extractSeed32FromPkcs8B64(keyBundle.recoveryPair.privatePkcs8B64)),
}));
// Root key
const rootSep = document.createElement('p');
rootSep.className = 'field-label';
rootSep.textContent = 'Root key';
rootSep.textContent = 'Root key (recovery)';
card.append(rootSep);
card.append(makePublicField({
label: 'Root — публичный (base58)',
label: 'Root / recovery — публичный (base58)',
value: bytesToBase58(base64ToBytes(keyBundle.rootPair.publicKeyB64)),
}));
card.append(makeSecretField({
label: 'Root — приватный (seed base58, 32 байта)',
label: 'Root / recovery — приватный (seed base58, 32 байта)',
value: bytesToBase58(extractSeed32FromPkcs8B64(keyBundle.rootPair.privatePkcs8B64)),
}));
+1 -1
View File
@@ -30,7 +30,7 @@ export const REGISTRATION_FAQ_TOPICS = [
title: 'Как генерируются ключи и что делает пароль?',
paragraphs: [
'Из вашего логина и пароля с помощью Argon2id вычисляется специальный секрет.',
'Уже из этого секрета детерминированно строятся четыре основных ключа: recovery key, root key, blockchain key и client key.',
'Уже из этого секрета детерминированно строятся три основных ключа: root/recovery key, blockchain key и client key.',
'Это значит, что логин и пароль не просто проверяются на сервере, а реально участвуют в создании ваших ключей. У разных логинов даже с одинаковым паролем будут разные ключи.',
],
},
+1 -6
View File
@@ -1133,11 +1133,7 @@ export class AuthService {
});
if (isCancelled && isCancelled()) throw new Error('DERIVE_CANCELLED');
if (onProgress) onProgress({ percent: 93, stage: 'derive', message: 'Вычисление recovery key...' });
const recoveryPair = await deriveEd25519FromMasterSecret(masterSecret, 'recovery.key');
if (isCancelled && isCancelled()) throw new Error('DERIVE_CANCELLED');
if (onProgress) onProgress({ percent: 95, stage: 'derive', message: 'Вычисление root key...' });
if (onProgress) onProgress({ percent: 94, stage: 'derive', message: 'Вычисление root key...' });
const rootPair = await deriveEd25519FromMasterSecret(masterSecret, 'root.key');
if (isCancelled && isCancelled()) throw new Error('DERIVE_CANCELLED');
@@ -1149,7 +1145,6 @@ export class AuthService {
const clientPair = await deriveEd25519FromMasterSecret(masterSecret, 'client.key');
const result = {
masterSecretB64: bytesToBase64(masterSecret),
recoveryPair,
rootPair,
blockchainPair,
clientPair,
File diff suppressed because it is too large Load Diff