SHA256
Обновление архитектуры ключей и кошельков
This commit is contained in:
@@ -285,9 +285,9 @@
|
||||
|
||||
## `KeyRotationContinue`
|
||||
|
||||
Продолжает интерактивные post-PDA этапы. В текущей версии два будущих этапа являются честными заглушками:
|
||||
Продолжает интерактивные post-PDA этапы. Сервер по-прежнему не хранит приватные ключи и сам не переводит средства. В текущем UI перед вызовом `KeyRotationContinue` на этапе `WALLET_MIGRATION` пользователь может перевести весь доступный SOL со старого blockchain-wallet на новый (или явно пропустить перенос). После этого сервер фиксирует этап как `NOT_IMPLEMENTED`/завершённый placeholder и переводит процесс дальше.
|
||||
|
||||
- `WALLET_MIGRATION`: `walletMigrationStatus = NOT_IMPLEMENTED`, затем переход в `MESSAGE_MIGRATION`;
|
||||
- `WALLET_MIGRATION`: клиентский UI выполняет перенос SOL локально, используя временно доступный старый blockchain private key; сервер только продолжает state machine. Перенос AR/Turbo пока TODO;
|
||||
- `MESSAGE_MIGRATION`: `messageMigrationStatus = NOT_IMPLEMENTED`, затем `FINALIZING -> COMPLETE`.
|
||||
|
||||
Request:
|
||||
@@ -300,7 +300,7 @@ Request:
|
||||
}
|
||||
```
|
||||
|
||||
`KeyRotationContinue` не переводит деньги и не перешифровывает DM. Это специально оставленные точки расширения для будущей реализации.
|
||||
`KeyRotationContinue` сам не переводит деньги и не перешифровывает DM. SOL-перевод реализован на стороне UI до этого запроса; серверная часть WALLET_MIGRATION остаётся точкой координации. AR/Turbo и DM остаются отдельными точками расширения.
|
||||
|
||||
## `KeyRotationAbort`
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ TEXT-тип хранит сообщения, материалы и редакт
|
||||
[32] toBlockHash32
|
||||
```
|
||||
|
||||
`toForkNumber`: `1..999` — fork, который видел автор действия; `0` зарезервирован как unknown/legacy. Поле информационное и **не входит в логическую идентичность цели**. Цель определяется только `toLogin + toBlockGlobalNumber + toBlockHash32`; несовпадение текущего fork само по себе не инвалидирует ссылку.
|
||||
`toForkNumber`: строго `1..999` — fork, который видел автор действия. Поле информационное и **не входит в логическую идентичность цели**. Цель определяется только `toLogin + toBlockGlobalNumber + toBlockHash32`; несовпадение текущего fork само по себе не инвалидирует ссылку.
|
||||
|
||||
Собственные edit (`TEXT_EDIT_POST`, `TEXT_EDIT_REPLY`) используют компактный target:
|
||||
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
[32] toBlockHash32
|
||||
```
|
||||
|
||||
`toForkNumber` — только историческая метка (`1..999`, `0` reserved unknown/legacy). Логическая идентичность реакции: `toLogin + toBlockGlobalNumber + toBlockHash32`. При fork номер fork может измениться; если number+hash сохранены в новой ветке, LIKE/UNLIKE продолжает указывать на тот же логический блок.
|
||||
`toForkNumber` — только историческая метка и всегда находится в диапазоне `1..999`. Логическая идентичность реакции: `toLogin + toBlockGlobalNumber + toBlockHash32`. При fork номер fork может измениться; если number+hash сохранены в новой ветке, LIKE/UNLIKE продолжает указывать на тот же логический блок.
|
||||
|
||||
@@ -30,7 +30,7 @@ CONNECTION-тип описывает социальные связи и подп
|
||||
[32] toBlockHash32
|
||||
```
|
||||
|
||||
`toForkNumber` хранит fork, который видел автор связи (`1..999`), но не участвует в identity. `0` зарезервирован как unknown/legacy; `1000+` недопустим. Для связи на пользователя используется **реальный HEADER hash**: `toBlockGlobalNumber=0`, `toBlockHash32=SHA-256(Frame HEADER)`. Нулевой hash запрещён.
|
||||
`toForkNumber` хранит fork, который видел автор связи (`1..999`), но не участвует в identity. Значения `0` и `1000+` недопустимы. Для связи на пользователя используется **реальный HEADER hash**: `toBlockGlobalNumber=0`, `toBlockHash32=SHA-256(Frame HEADER)`. Нулевой hash запрещён.
|
||||
|
||||
## Правила target
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
Где:
|
||||
|
||||
- `toLogin` — login владельца целевого блока;
|
||||
- `toForkNumber` — историческая метка fork (`1..999`, `0` reserved unknown/legacy), не часть identity;
|
||||
- `toForkNumber` — историческая метка fork (`1..999`), не часть identity;
|
||||
- `toBlockGlobalNumber` — номер целевого блока;
|
||||
- `toBlockHash32` — хэш целевого блока;
|
||||
- `text` — опциональное пояснение пользователя к статусу.
|
||||
|
||||
@@ -17,7 +17,7 @@ Block 0 новой пользовательской истории — `HEADER`:
|
||||
SHiNE + login + initialBlockchainKey32
|
||||
```
|
||||
|
||||
`initialBlockchainKey32` — public blockchain-signing key fork №1. При смене ключа сохранённый префикс, включая HEADER, перепубликуется с тем же Frame; поэтому это поле остаётся исходным ключом, а новый ключ конкретного fork определяется подписью/owner и PDA.
|
||||
`initialBlockchainKey32` — public blockchain-signing key fork №1. Это только историческая запись происхождения цепочки. При смене ключа сохранённый префикс, включая HEADER, перепубликуется с тем же Frame; поле остаётся исходным ключом и не сравнивается с текущим ключом fork. Текущий ключ конкретного fork определяется подписью/owner и PDA.
|
||||
|
||||
## 3. Внешний target
|
||||
|
||||
@@ -31,7 +31,7 @@ SHiNE + login + initialBlockchainKey32
|
||||
[32] toBlockHash32
|
||||
```
|
||||
|
||||
`toForkNumber` — информационная историческая метка: fork, на который смотрел автор действия. `0` зарезервирован как unknown/legacy и не является реальным fork. Поле не участвует в identity и не должно сравниваться с текущим active fork как условие валидности.
|
||||
`toForkNumber` — информационная историческая метка: fork, на который смотрел автор действия. Допустимы только реальные fork `1..999`; `0` запрещён. Поле не участвует в identity и не должно сравниваться с текущим active fork как условие валидности.
|
||||
|
||||
Логическая identity цели:
|
||||
|
||||
|
||||
+16
-4
@@ -55,8 +55,8 @@ seed(32) = SHA-256(material)
|
||||
| Ключ | Суффикс | Назначение (кратко) |
|
||||
|------|---------|---------------------|
|
||||
| root | `root.key` | Личность. Подписывает unsigned-часть PDA-записи (`RootKeyBlock`). |
|
||||
| blockchain | `blockchain.key` | Подписывает пользовательские блоки/ANS-104 DataItem и является текущим Solana-wallet/fee payer. |
|
||||
| client | `client.key` | Общий клиентский ключ для DM/устройств и derivation отдельного Arweave SAWD-кошелька; не является текущим Solana-wallet. |
|
||||
| blockchain | `blockchain.key` | Подписывает пользовательские блоки/ANS-104 DataItem и является каноническим источником пользовательских кошельков: Solana и Arweave SAWD-v1. |
|
||||
| client | `client.key` | Общий клиентский ключ для входа на сервер, устройств и DM. Не используется как источник штатных кошельков. |
|
||||
| homeserver | `homeserver.key:<имя>` | Ключ homeserver-устройства, по одному на каждый homeserver (различитель — имя). См. §4. |
|
||||
|
||||
Полные роли каждого ключа — в `docs/Keys/README.md`.
|
||||
@@ -75,9 +75,21 @@ seed(32) = SHA-256(material)
|
||||
|
||||
`root.key` не является fee payer. Он используется как холодное дополнительное разрешение только для полной ротации root + client + blockchain fork.
|
||||
|
||||
`client.key` больше не используется как Solana-wallet/fee payer. Он остаётся клиентским криптографическим ключом (DM/устройства) и входом в отдельный протокол derivation Arweave-кошелька.
|
||||
`client.key` не используется как wallet/fee payer. Он остаётся клиентским криптографическим ключом для серверной авторизации, устройств и DM. Нативный Arweave SAWD-v1 wallet теперь детерминированно выводится из активного `blockchain.key`, как и Solana-wallet.
|
||||
|
||||
При fork Solana-адрес меняется вместе с blockchain key. Перенос SOL со старого blockchain-wallet на новый является отдельным необязательным этапом ротации; в текущей первой реализации этот этап оставлен явной заглушкой.
|
||||
При fork адреса кошельков меняются вместе с blockchain key. В UI ротации реализован отдельный этап переноса доступного SOL со старого blockchain-wallet на новый за вычетом комиссии сети. Перенос AR/Turbo при ротации пока отмечен отдельным TODO.
|
||||
|
||||
|
||||
## 3.1. Хранение приватных ключей в текущем UI
|
||||
|
||||
После обычного входа или подключения нового доверенного устройства UI автоматически сохраняет в зашифрованном локальном контейнере два рабочих приватных ключа:
|
||||
|
||||
- `blockchain.key`;
|
||||
- `client.key`.
|
||||
|
||||
Приватный `root.key` (Recovery key) **никогда не сохраняется** в IndexedDB/localStorage и **никогда не передаётся** при pairing/QR. Для операций, которым он нужен по текущему Solana-протоколу, root временно выводится из введённого пользователем пароля и существует только в оперативной памяти процесса. Публичный root key, записанный в PDA, этим правилом не затрагивается.
|
||||
|
||||
Ограниченный режим устройства архитектурно возможен благодаря разделению ключей, но в текущем релизе не включён: обычное авторизованное устройство всегда получает и хранит оба рабочих ключа.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+20
-30
@@ -8,16 +8,16 @@
|
||||
|
||||
В SHiNE у пользователя есть несколько уровней ключей:
|
||||
|
||||
- `root key` - холодный recovery-ключ: при полной ротации дополнительно разрешает замену root + client + blockchain fork. Это не кошелёк.
|
||||
- `blockchain key` - ключ записи в персональный SHiNE-блокчейн и текущий Solana-wallet/fee payer пользователя.
|
||||
- `client key` - общий ключ пользовательских устройств для повседневной работы, звонков и DM; Solana-wallet им больше не является.
|
||||
- `root key` / **ключ восстановления** - recovery-authority. Его приватная часть не хранится на устройствах и временно выводится из пароля только для операций, где нужна по текущему протоколу. Это не кошелёк.
|
||||
- `blockchain key` / **ключ блокчейна** - постоянно хранимый рабочий ключ записи в персональный SHiNE-блокчейн и канонический источник пользовательских кошельков (Solana, Arweave SAWD-v1, Turbo через Solana).
|
||||
- `client key` / **ключ доступа** - постоянно хранимый рабочий ключ для входа на сервер, устройства, звонков и DM. Кошельки из него не выводятся.
|
||||
- `session key` - ключ конкретной сессии или конкретного устройства для авторизации на сервере.
|
||||
|
||||
Главная идея: самые важные ключи можно держать на доверенном серверном или аппаратном устройстве, а обычные клиентские устройства получают только ключи, нужные для текущей работы.
|
||||
В текущем релизе обычное авторизованное устройство автоматически хранит два рабочих ключа: `blockchain key` и `client key`. Ограниченного режима пока нет. Приватный `root key` не сохраняется и не передаётся между устройствами.
|
||||
|
||||
## `root key`
|
||||
|
||||
`root key` - главный ключ пользователя.
|
||||
`root key` - ключ восстановления пользователя. Его приватная часть не является постоянно сохранённым ключом устройства.
|
||||
|
||||
Назначение:
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
Обычные PDA-update **не требуют root key**: их выполняет активный blockchain key. При полной ротации старый root подписывает тот же hash нового unsigned PDA state, который подписывает новый blockchain key. Так root разрешает переход, не становясь повседневным ключом.
|
||||
|
||||
Важно не путать recovery-authority и кошелёк: `root key` не является fee payer. Текущий Solana-wallet/fee payer — активный `blockchain key`. Подробнее — `docs/Keys/DERIVATION.md`, §3.
|
||||
Важно не путать recovery-authority и кошелёк: `root key` не является fee payer. Его публичная часть хранится в PDA, а приватная часть в текущем UI выводится из пароля только на время защищённой операции и затем не сохраняется. Текущий Solana-wallet/fee payer — активный `blockchain key`. Подробнее — `docs/Keys/DERIVATION.md`, §3.
|
||||
|
||||
## `blockchain key`
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
- подпись записей в персональном блокчейне пользователя;
|
||||
- подтверждение действий, которые должны попасть в SHiNE-блокчейн;
|
||||
- обычные обновления пользовательской PDA;
|
||||
- текущий Solana-wallet/fee payer (`base58(active blockchain public key)`).
|
||||
- текущий Solana-wallet/fee payer (`base58(active blockchain public key)`);
|
||||
- источник штатного Arweave SAWD-v1 wallet;
|
||||
- ключ Solana-кошелька, которым пополняется Turbo.
|
||||
|
||||
У пользователя может быть несколько персональных блокчейнов или веток. При смене `blockchain key` фактически создаётся новая ветка записи:
|
||||
|
||||
@@ -58,15 +60,9 @@
|
||||
|
||||
- повседневные входящие и исходящие личные сообщения;
|
||||
- звонки и связанные с ними сообщения;
|
||||
- self-messages, то есть внутренние сообщения пользователя самому себе;
|
||||
- derivation Arweave-кошелька;
|
||||
- оплата или подготовка добавления данных в Arweave-кошелек по отдельному протоколу.
|
||||
- self-messages, то есть внутренние сообщения пользователя самому себе.
|
||||
|
||||
Arweave-кошелёк должен выводиться из `client key` по протоколу:
|
||||
|
||||
- `docs/Протоколы/SHINE_ARWEAVE_DERIVATION_V1.md`
|
||||
|
||||
Если пользователь теряет только `client key`, в худшем случае ломается повседневная переписка и доступ конкретных устройств к ежедневным операциям. `root key` и `blockchain key` при правильной архитектуре остаются отдельно защищёнными.
|
||||
Штатные кошельки из `client key` не выводятся. Arweave SAWD-v1 использует `blockchain key`: `docs/Протоколы/SHINE_ARWEAVE_DERIVATION_V1.md`.
|
||||
|
||||
## `session key`
|
||||
|
||||
@@ -82,7 +78,7 @@ Arweave-кошелёк должен выводиться из `client key` по
|
||||
- авторизация сессии на сервере;
|
||||
- привязка устройства к пользователю;
|
||||
- подтверждение запросов от конкретной сессии;
|
||||
- доступ к зашифрованному `client key` после успешной авторизации.
|
||||
- доступ к локально зашифрованным рабочим ключам (`client key` и `blockchain key`) после успешной авторизации.
|
||||
|
||||
Одна и та же сессия может быть пригодна для подключения к нескольким серверам пользователя, если архитектура конкретного пользователя это допускает.
|
||||
|
||||
@@ -102,22 +98,16 @@ Arweave-кошелёк должен выводиться из `client key` по
|
||||
|
||||
- обычная пользовательская сессия;
|
||||
- серверная сессия;
|
||||
- аппаратная или доверенная сессия с доступом к расширенным ключам.
|
||||
- аппаратная или доверенная сессия для будущих специализированных сценариев.
|
||||
|
||||
Обычное устройство обычно имеет:
|
||||
Обычное авторизованное устройство в текущем релизе имеет:
|
||||
|
||||
- собственный `session key`;
|
||||
- зашифрованный `client key`, который открывается после авторизации;
|
||||
- доступ к DM, звонкам и обычным пользовательским операциям.
|
||||
- зашифрованный `client key`;
|
||||
- зашифрованный `blockchain key`;
|
||||
- доступ к DM, блокчейн-действиям и пользовательским кошелькам.
|
||||
|
||||
Доверенное серверное или аппаратное устройство может иметь:
|
||||
|
||||
- `root key`;
|
||||
- `blockchain key`;
|
||||
- `client key`;
|
||||
- собственный `session key`.
|
||||
|
||||
Такая сессия может подписывать операции повышенной важности по запросам пользователя.
|
||||
Приватный `root key` не хранится даже на обычном доверенном устройстве и не передаётся при подключении другого устройства. Будущий аппаратный режим может расширить эту модель отдельно, но текущий UI такого режима не включает.
|
||||
|
||||
## Внутренние self-messages
|
||||
|
||||
@@ -126,7 +116,7 @@ Self-message - это сообщение пользователя самому
|
||||
Такие сообщения нужны, чтобы обычное устройство могло попросить доверенное устройство выполнить действие:
|
||||
|
||||
- подписать запись `blockchain key` и передать её в SHiNE-блокчейн;
|
||||
- подписать изменение настройки через `root key`;
|
||||
- инициировать защищённую настройку, после чего Recovery key при необходимости должен быть временно выведен из пароля на устройстве пользователя;
|
||||
- обновить ключи;
|
||||
- сохранить внутреннюю команду или настройку;
|
||||
- отправить сообщение другому пользователю с сохранением копии себе;
|
||||
@@ -163,7 +153,7 @@ Self-message - это сообщение пользователя самому
|
||||
- `docs/Blockchain/README.md` - точка входа по форматам SHiNE-блокчейна.
|
||||
- `docs/Solana_Architecture/README.md` - архитектура Solana-программ, PDA-счетов, DAO и движения средств.
|
||||
- `docs/Инициализация_Solana_регистрации/README.md` - деплой и первичная инициализация Solana-регистрации.
|
||||
- `docs/Протоколы/SHINE_ARWEAVE_DERIVATION_V1.md` - derivation Arweave-кошелька из `client key`.
|
||||
- `docs/Протоколы/SHINE_ARWEAVE_DERIVATION_V1.md` - derivation Arweave-кошелька из `blockchain key`.
|
||||
|
||||
## Что нужно уточнить перед реализацией
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
Сокращение: **SAWD-v1**.
|
||||
|
||||
## Назначение
|
||||
Из 32-байтного `clientKey32` пользователя получить один и тот же нативный Arweave RSA-4096 JWK wallet и один и тот же Arweave address.
|
||||
Из 32-байтного приватного seed активного `blockchainKey32` пользователя получить один и тот же нативный Arweave RSA-4096 JWK wallet и один и тот же Arweave address.
|
||||
|
||||
## Вход
|
||||
- `clientKey32`: ровно 32 байта.
|
||||
- Если исходный `client.key` хранится как Ed25519 PKCS8 base64, нужно извлечь последние 32 байта из PKCS8.
|
||||
- `blockchainKey32`: ровно 32 байта.
|
||||
- Если исходный `blockchain.key` хранится как Ed25519 PKCS8 base64, нужно извлечь последние 32 байта из PKCS8.
|
||||
- Если используется Solana keypair JSON на 64 байта, используются только `bytes[0..31]`.
|
||||
|
||||
## Выход
|
||||
@@ -46,8 +46,8 @@
|
||||
- `SMALL_PRIME_LIMIT = 10000`
|
||||
|
||||
## Алгоритм
|
||||
1. Проверить `clientKey32.length == 32`.
|
||||
2. `masterSeed32 = HMAC-SHA256(key = UTF8(MASTER_LABEL), message = clientKey32)`.
|
||||
1. Проверить `blockchainKey32.length == 32`.
|
||||
2. `masterSeed32 = HMAC-SHA256(key = UTF8(MASTER_LABEL), message = blockchainKey32)`.
|
||||
3. Реализовать `deriveBytes(label, length)`:
|
||||
- `output = empty`
|
||||
- `counter = 0`
|
||||
@@ -71,9 +71,9 @@
|
||||
- `baseBytes = HMAC-SHA256(key = masterSeed32, message = UTF8(MR_LABEL) || UTF8("/") || UTF8(label) || UTF8("/") || uint64_be(index) || UTF8("/") || uint32_be(round))`
|
||||
- `a = 2 + (unsigned_big_endian_integer(baseBytes) mod (candidate - 3))`
|
||||
6. `p = derivePrime("p")`, `q = derivePrime("q")`.
|
||||
7. Если `p == q`, продолжить поиск `q`.
|
||||
7. Продолжать детерминированный поиск `q` (`q/index+1`, `q/index+2`, ...), если `p == q` **или** `bitLength(p * q) != 4096`. Это гарантирует настоящий 4096-битный RSA modulus, а не допустимый математически, но неподходящий для стандарта 4095-битный product двух 2048-битных простых.
|
||||
8. Если `p > q`, поменять местами. В SAWD-v1 всегда `p < q`.
|
||||
9. `n = p * q`
|
||||
9. `n = p * q`; обязательно `bitLength(n) == 4096`
|
||||
10. `e = 65537`
|
||||
11. `lambda = lcm(p - 1, q - 1)`
|
||||
12. `d = modular_inverse(e, lambda)`
|
||||
@@ -101,4 +101,4 @@
|
||||
|
||||
## Версионирование стандарта
|
||||
Если меняется любая константа или шаг алгоритма — это уже **SAWD-v2**.
|
||||
Пользователи, созданные на SAWD-v1, должны продолжать восстанавливаться через SAWD-v1.
|
||||
До публичного запуска legacy-совместимость не требуется. После запуска источник и алгоритм SAWD-v1 считаются частью стабильного формата: изменение источника ключа или любой константы потребует новой версии стандарта.
|
||||
|
||||
Reference in New Issue
Block a user