# Обновление авторизации для совместимости с crypto_new

## Дата: 16 января 2026

## Статус: ✅ Реализовано

## Обзор изменений

Обновлена логика авторизации в Android приложении для полной совместимости с новым методом шифрования из `crypto_new` (TypeScript/JavaScript). Основные изменения касаются генерации ключевых пар и формата публичных ключей.

## Основные изменения

### 1. Метод генерации приватного ключа

#### Старый метод (BIP39):

```kotlin
fun seedPhraseToPrivateKey(seedPhrase: List<String>): String {
    val mnemonicCode = MnemonicCode.INSTANCE
    val seed = MnemonicCode.toSeed(seedPhrase, "")  // 64 bytes
    return seed.joinToString("") { "%02x".format(it) }  // 128 hex chars
}
```

#### Новый метод (crypto_new):

```kotlin
fun seedPhraseToPrivateKey(seedPhrase: List<String>): String {
    val seedString = seedPhrase.joinToString(" ")
    val digest = MessageDigest.getInstance("SHA-256")
    val hash = digest.digest(seedString.toByteArray(Charsets.UTF_8))  // 32 bytes
    return hash.joinToString("") { "%02x".format(it) }  // 64 hex chars
}
```

**JavaScript эквивалент (crypto_new/crypto.ts):**

```javascript
const privateKey = sha256.create().update(seed).digest().toHex().toString();
```

### 2. Формат публичного ключа

#### Старый метод (несжатый):

```kotlin
val publicKeyPoint = ecSpec.g.multiply(privateKeyBigInt)
val publicKeyHex = publicKeyPoint.getEncoded(false)  // 65 bytes (04 + x + y)
```

#### Новый метод (сжатый):

```kotlin
val publicKeyPoint = ecSpec.g.multiply(privateKeyBigInt)
val publicKeyHex = publicKeyPoint.getEncoded(true)  // 33 bytes (02/03 + x)
```

**JavaScript эквивалент (crypto_new/crypto.ts):**

```javascript
const publicKey = secp256k1.getPublicKey(Buffer.from(privateKey, "hex"), true);
```

### 3. Метод генерации privateKeyHash

Этот метод **НЕ ИЗМЕНИЛСЯ** и уже был совместим с crypto_new:

```kotlin
fun generatePrivateKeyHash(privateKey: String): String {
    val data = (privateKey + "rosetta").toByteArray()
    val digest = MessageDigest.getInstance("SHA-256")
    val hash = digest.digest(data)
    return hash.joinToString("") { "%02x".format(it) }
}
```

**JavaScript эквивалент (crypto_new/crypto.ts):**

```javascript
export const generateHashFromPrivateKey = async (privateKey: string) => {
  return sha256
    .create()
    .update(privateKey + "rosetta")
    .digest()
    .toHex()
    .toString();
};
```

## Изменённые файлы

### CryptoManager.kt

**Файл:** `/app/src/main/java/com/rosetta/messenger/crypto/CryptoManager.kt`

**Изменённые функции:**

1. `seedPhraseToPrivateKey()` - теперь использует SHA256 вместо BIP39
2. `generateKeyPairFromSeed()` - генерирует сжатый публичный ключ (33 байта)

## Влияние на авторизацию

### Процесс авторизации

1. **Создание аккаунта (`AuthState.kt -> createAccount()`):**

   ```kotlin
   val keyPair = CryptoManager.generateKeyPairFromSeed(seedPhrase)
   // keyPair.privateKey - 32 bytes (64 hex chars) через SHA256
   // keyPair.publicKey - 33 bytes (66 hex chars) сжатый формат

   val privateKeyHash = CryptoManager.generatePrivateKeyHash(keyPair.privateKey)
   // SHA256(privateKey + "rosetta")
   ```

2. **Подключение к серверу (`Protocol.kt -> startHandshake()`):**

   ```kotlin
   val handshake = PacketHandshake().apply {
       this.publicKey = keyPair.publicKey      // 33 bytes сжатый
       this.privateKey = privateKeyHash        // SHA256 hash
   }
   ```

3. **Сервер проверяет:**
   - Публичный ключ в сжатом формате (33 байта)
   - privateKeyHash = SHA256(privateKey + "rosetta")

## Совместимость

### ✅ Совместимо с crypto_new

- **Генерация ключей:** SHA256(seedPhrase) → privateKey
- **Публичный ключ:** Сжатый формат (33 байта)
- **privateKeyHash:** SHA256(privateKey + "rosetta")
- **ECDH:** Поддерживает сжатые ключи через `decodePoint()`

### ⚠️ Несовместимость со старыми аккаунтами

**ВАЖНО:** Аккаунты, созданные со старым методом (BIP39 + несжатый ключ), больше НЕ СМОГУТ авторизоваться!

Причины:

1. Другой приватный ключ (BIP39 vs SHA256)
2. Другой публичный ключ (65 байт vs 33 байта)
3. Другой privateKeyHash (из-за другого privateKey)

### Миграция

Для поддержки старых аккаунтов потребуется:

1. **Определить формат ключа при загрузке:**

   ```kotlin
   fun isOldFormat(publicKey: String): Boolean {
       return publicKey.length == 130  // 65 bytes = 130 hex chars
   }
   ```

2. **Использовать соответствующий метод генерации**

**НО:** Рекомендуется создать новые аккаунты с новым методом шифрования!

## Тестирование

### Проверка совместимости

1. **Создать тестовый seed phrase:**

   ```
   test seed phrase for crypto new compatibility check here now
   ```

2. **JavaScript (crypto_new):**

   ```javascript
   const keyPair = await generateKeyPairFromSeed(
     "test seed phrase for crypto new compatibility check here now"
   );
   console.log("Private:", keyPair.privateKey);
   console.log("Public:", keyPair.publicKey);
   console.log("Hash:", await generateHashFromPrivateKey(keyPair.privateKey));
   ```

3. **Kotlin (Android):**

   ```kotlin
   val seedPhrase = listOf("test", "seed", "phrase", "for", "crypto", "new", "compatibility", "check", "here", "now")
   val keyPair = CryptoManager.generateKeyPairFromSeed(seedPhrase)
   val hash = CryptoManager.generatePrivateKeyHash(keyPair.privateKey)

   Log.d("Test", "Private: ${keyPair.privateKey}")
   Log.d("Test", "Public: ${keyPair.publicKey}")
   Log.d("Test", "Hash: $hash")
   ```

4. **Результаты должны совпадать на 100%!**

### Проверка авторизации

1. Создать новый аккаунт в Android приложении
2. Сохранить seed phrase
3. Импортировать тот же seed phrase в React Native версии
4. Убедиться что оба приложения:
   - Генерируют одинаковые ключи
   - Успешно авторизуются на сервере
   - Могут отправлять/получать сообщения друг другу

## Преимущества нового метода

### 1. Простота

- Один SHA256 вместо сложной BIP39 генерации
- Меньше зависимостей

### 2. Совместимость

- 100% совместимость с JavaScript crypto_new
- Одинаковые ключи на всех платформах

### 3. Размер

- Сжатые публичные ключи: 33 байта вместо 65
- Экономия трафика и места в БД

### 4. Производительность

- SHA256 быстрее чем BIP39 derivation
- Кэширование результатов

## Потенциальные проблемы

### 1. Миграция существующих пользователей

**Решение:** Требуется создание новых аккаунтов с новым seed phrase.

### 2. Обратная совместимость

**Решение:** Можно добавить проверку формата ключа и поддержку обоих методов:

```kotlin
fun generateKeyPairFromSeed(
    seedPhrase: List<String>,
    useNewMethod: Boolean = true
): KeyPairData {
    return if (useNewMethod) {
        // Новый метод: SHA256 + compressed
        generateKeyPairFromSeedNew(seedPhrase)
    } else {
        // Старый метод: BIP39 + uncompressed
        generateKeyPairFromSeedLegacy(seedPhrase)
    }
}
```

### 3. Безопасность

**SHA256(seedPhrase) vs BIP39:**

- BIP39 использует PBKDF2 с 2048 итераций
- SHA256 - один проход

**Рекомендация:** Для production рассмотреть использование PBKDF2 в crypto_new:

```javascript
// Более безопасная версия
const privateKey = crypto
  .PBKDF2(seed, "rosetta", {
    keySize: 256 / 32,
    iterations: 2048,
  })
  .toString();
```

## Заключение

Авторизация полностью обновлена для совместимости с crypto_new. Все ключи генерируются одинаково на Android и JavaScript платформах, что обеспечивает:

- ✅ Единую базу кода для криптографии
- ✅ Совместимость между платформами
- ✅ Уменьшение размера ключей
- ✅ Улучшение производительности

**Следующие шаги:**

1. Тестирование авторизации на реальном сервере
2. Проверка обмена сообщениями между Android и React Native
3. Документирование процесса миграции для существующих пользователей
