SHA256
API: задокументирован rawBlockB64 в GetMessageThread и обновлены версии
This commit is contained in:
@@ -1,104 +0,0 @@
|
||||
# SHiNE Arweave Wallet Derivation v1
|
||||
|
||||
Сокращение: **SAWD-v1**.
|
||||
|
||||
## Назначение
|
||||
Из 32-байтного `deviceKey32` пользователя получить один и тот же нативный Arweave RSA-4096 JWK wallet и один и тот же Arweave address.
|
||||
|
||||
## Вход
|
||||
- `deviceKey32`: ровно 32 байта.
|
||||
- Если исходный `device.key` хранится как Ed25519 PKCS8 base64, нужно извлечь последние 32 байта из PKCS8.
|
||||
- Если используется Solana keypair JSON на 64 байта, используются только `bytes[0..31]`.
|
||||
|
||||
## Выход
|
||||
```json
|
||||
{
|
||||
"derivation": "SAWD-v1",
|
||||
"jwk": {
|
||||
"kty": "RSA",
|
||||
"e": "AQAB",
|
||||
"n": "...",
|
||||
"d": "...",
|
||||
"p": "...",
|
||||
"q": "...",
|
||||
"dp": "...",
|
||||
"dq": "...",
|
||||
"qi": "..."
|
||||
},
|
||||
"owner": "...",
|
||||
"address": "..."
|
||||
}
|
||||
```
|
||||
|
||||
Где:
|
||||
- `owner = jwk.n`
|
||||
- `address = base64url_no_padding(SHA-256(unsigned_big_endian_bytes(n)))`
|
||||
|
||||
## Константы
|
||||
- `DERIVATION_NAME = "SAWD-v1"`
|
||||
- `MASTER_LABEL = "SHINE/ARWEAVE/RSA4096/SAWD-v1/MASTER"`
|
||||
- `STREAM_LABEL = "SHINE/ARWEAVE/RSA4096/SAWD-v1/STREAM"`
|
||||
- `MR_LABEL = "SHINE/ARWEAVE/RSA4096/SAWD-v1/MILLER-RABIN"`
|
||||
- `RSA_BITS = 4096`
|
||||
- `PRIME_BITS = 2048`
|
||||
- `PUBLIC_EXPONENT = 65537`
|
||||
- `MILLER_RABIN_ROUNDS = 64`
|
||||
- `SMALL_PRIME_LIMIT = 10000`
|
||||
|
||||
## Алгоритм
|
||||
1. Проверить `deviceKey32.length == 32`.
|
||||
2. `masterSeed32 = HMAC-SHA256(key = UTF8(MASTER_LABEL), message = deviceKey32)`.
|
||||
3. Реализовать `deriveBytes(label, length)`:
|
||||
- `output = empty`
|
||||
- `counter = 0`
|
||||
- while `output.length < length`:
|
||||
- `block = HMAC-SHA256(key = masterSeed32, message = UTF8(STREAM_LABEL) || UTF8("/") || UTF8(label) || UTF8("/") || uint64_be(counter))`
|
||||
- `output = output || block`
|
||||
- `counter++`
|
||||
- вернуть первые `length` байт.
|
||||
4. Для `p` и `q`:
|
||||
- `raw = deriveBytes(label + "/" + index, 256)`
|
||||
- `candidate = unsigned_big_endian_integer(raw)`
|
||||
- `candidate = candidate OR 2^2047`
|
||||
- `candidate = candidate OR 1`
|
||||
- Проверить:
|
||||
- `bitLength(candidate) == 2048`
|
||||
- `candidate odd`
|
||||
- не делится на малые простые `<= 10000`
|
||||
- `gcd(candidate - 1, 65537) == 1`
|
||||
- проходит Miller-Rabin `64 rounds`
|
||||
5. Базы Miller-Rabin детерминированные:
|
||||
- `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`.
|
||||
8. Если `p > q`, поменять местами. В SAWD-v1 всегда `p < q`.
|
||||
9. `n = p * q`
|
||||
10. `e = 65537`
|
||||
11. `lambda = lcm(p - 1, q - 1)`
|
||||
12. `d = modular_inverse(e, lambda)`
|
||||
13. `dp = d mod (p - 1)`
|
||||
14. `dq = d mod (q - 1)`
|
||||
15. `qi = modular_inverse(q, p)`
|
||||
16. Сформировать JWK:
|
||||
- `kty = "RSA"`
|
||||
- `e = "AQAB"`
|
||||
- `n,d,p,q,dp,dq,qi = base64url unsigned big-endian integer without padding`
|
||||
17. `owner = jwk.n`
|
||||
18. `address = base64url_no_padding(SHA-256(unsigned_big_endian_bytes(n)))`
|
||||
|
||||
## Запрещено
|
||||
- `crypto.generateKeyPair`
|
||||
- `WebCrypto generateKey`
|
||||
- `KeyPairGenerator`
|
||||
- `SecureRandom(seed)`
|
||||
- `Math.random`
|
||||
- системный `random`
|
||||
- ArDrive CLI
|
||||
- Turbo
|
||||
- внешний API для генерации ключа
|
||||
- сохранение приватного JWK
|
||||
|
||||
## Версионирование стандарта
|
||||
Если меняется любая константа или шаг алгоритма — это уже **SAWD-v2**.
|
||||
Пользователи, созданные на SAWD-v1, должны продолжать восстанавливаться через SAWD-v1.
|
||||
@@ -1,105 +0,0 @@
|
||||
Дата: 27.04.2026
|
||||
|
||||
# Ответ по блокчейну, форматам, каналам и расширяемости
|
||||
|
||||
Короткий итог: текущую систему можно запускать и развивать дальше. Архитектура уже в целом готова к расширению версиями, но расширять нужно по строгим правилам совместимости.
|
||||
|
||||
## 1) Что важно зафиксировать про эволюцию форматов
|
||||
|
||||
Да, ваш подход верный:
|
||||
- новые возможности добавляем через новые `type/subType/version` и/или новый `frameCode`;
|
||||
- старые блоки не переписываем и не «переподписываем»;
|
||||
- делаем конвертер/адаптер чтения: старые блоки читаются и приводятся к новой внутренней модели.
|
||||
|
||||
Это и есть правильная схема «старое автоматически читается и представляется в новом формате».
|
||||
|
||||
## 2) Есть ли в коде узкие места, где нельзя расширять
|
||||
|
||||
Критичных тупиков не видно, но есть важные ограничения:
|
||||
- Парсер сейчас строгий: неизвестные `type/subType/version` и неизвестный frame отклоняются.
|
||||
- Значит новые форматы нужно явно добавлять в парсер и серверную валидацию.
|
||||
- Старые блоки без нужных полей не проблема, если новый код умеет читать их как legacy-ветку.
|
||||
|
||||
Вывод: расширение возможно, но только через явную поддержку версий, а не «само появится».
|
||||
|
||||
## 3) Про канал `0`
|
||||
|
||||
Зафиксировано правило:
|
||||
- канал `0` оставляем как технический root;
|
||||
- контент-посты туда пока не публикуем.
|
||||
|
||||
Это теперь отмечено в коде комментариями и проверками:
|
||||
- на клиенте (UI) пост в `lineCode=0` блокируется с понятной ошибкой;
|
||||
- на сервере добавлена валидация, которая тоже отклоняет `TEXT_POST` в канал `0`.
|
||||
|
||||
## 4) Формат аватара (`ava`) — обновлено
|
||||
|
||||
Раньше:
|
||||
- `AR:<txId>`
|
||||
|
||||
Теперь поддерживается составной формат:
|
||||
- `SHA256:<hash>,AR:<txId>`
|
||||
|
||||
Что сделано:
|
||||
- парсер и сборщик формата в UI обновлены;
|
||||
- при загрузке нового аватара считается `SHA-256` оптимизированного файла и сохраняется вместе с `AR`;
|
||||
- при выборе существующего `txId` сначала качается файл, считается `SHA-256`, и только потом пишется `ava`;
|
||||
- серверный граф связей теперь умеет извлекать `AR` из составной строки (включая fallback для legacy/кривых значений).
|
||||
|
||||
Это улучшает целостность: у вас есть не только адрес файла, но и контрольный хэш.
|
||||
|
||||
## 5) Как устроены ответы в каналах и насколько это надёжно
|
||||
|
||||
Ответы (`REPLY` / `EDIT_REPLY`) сделаны отдельно от линейных постов:
|
||||
- `REPLY` хранит ссылку на цель (`toBlockchainName + blockNumber + hash32`) и текст;
|
||||
- `EDIT_REPLY` хранит ссылку на оригинальный reply (`blockNumber + hash32`) и новый текст.
|
||||
|
||||
Сильные стороны:
|
||||
- ссылка идёт по номеру + хэшу (устойчиво к подмене цели);
|
||||
- редактирование отделено от оригинала и может агрегироваться в чтении.
|
||||
|
||||
Для будущего это расширяемо:
|
||||
- можно добавить `TEXT_REPLY_V2` с новым payload, сохранив `V1` для старых клиентов.
|
||||
|
||||
## 6) Вложенные файлы и «мини-разметка» внутри сообщения
|
||||
|
||||
Идея рабочая, но лучше делать аккуратно.
|
||||
|
||||
### Вариант A: «теги в тексте» (ваша идея)
|
||||
|
||||
Плюсы:
|
||||
- быстро внедрить;
|
||||
- стандартно для пользователей (похоже на HTML/Markdown).
|
||||
|
||||
Риски:
|
||||
- экранирование `<` `>` и безопасность рендера;
|
||||
- сложнее валидировать и безопасно отображать (XSS/инъекции).
|
||||
|
||||
Если идти этим путём, лучше:
|
||||
- разрешить только whitelist-теги (`img/file/h1/h2/h3/b/i` и т.д.);
|
||||
- хранить метаданные файла явно: `type,size,sha256,ar`;
|
||||
- рендерить через безопасный парсер, а не через «сырой HTML».
|
||||
|
||||
### Вариант B: структурированный payload (рекомендуется как основной)
|
||||
|
||||
Сделать `TEXT_POST_V2`:
|
||||
- массив сегментов: `text`, `image`, `file`, `heading`, `style`;
|
||||
- для файла хранить `kind`, `mime`, `size`, `sha256`, `storage`, `address`.
|
||||
|
||||
Плюс:
|
||||
- надёжная валидация и безопасный рендер.
|
||||
|
||||
Оптимальная стратегия:
|
||||
1. В UI можно дать «мини-разметку» для ввода.
|
||||
2. На запись преобразовывать её в структурированный payload V2.
|
||||
3. Для старых клиентов отдавать fallback plain text.
|
||||
|
||||
## 7) Практический roadmap без остановки разработки
|
||||
|
||||
1. Оставить текущий blockchain running.
|
||||
2. Формально описать versioning policy (что считается breaking/non-breaking).
|
||||
3. Зафиксировать channel `0` как технический root-only.
|
||||
4. Использовать `ava = SHA256 + AR` как новый стандарт.
|
||||
5. Запланировать `TEXT_*_V2` для вложений и форматирования.
|
||||
|
||||
Итог: стартовать и развивать можно уже сейчас. Основа хорошая, если строго держать версионирование и адаптеры чтения для legacy-блоков.
|
||||
Reference in New Issue
Block a user