feat: Update authorization logic for compatibility with crypto_new; enhance key generation and public key format

This commit is contained in:
k1ngsterr1
2026-01-16 04:53:48 +05:00
parent 306e854646
commit caf1d246d3
7 changed files with 774 additions and 15 deletions

View File

@@ -0,0 +1,192 @@
/**
* Тест совместимости Android crypto с crypto_new (JavaScript)
*
* Этот файл проверяет, что Android и JavaScript генерируют одинаковые ключи
* из одинаковой seed phrase.
*
* Для запуска теста:
* 1. Запустите этот тест в Android приложении
* 2. Скопируйте seed phrase из логов
* 3. Запустите test-crypto-new-compat.js с той же seed phrase
* 4. Сравните результаты - они должны совпадать!
*/
package com.rosetta.messenger.crypto
import org.junit.Test
import org.junit.Assert.*
import java.security.Security
import org.bouncycastle.jce.provider.BouncyCastleProvider
class CryptoNewCompatibilityTest {
init {
// Добавляем BouncyCastle provider
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(BouncyCastleProvider())
}
}
@Test
fun testKeyGenerationFromFixedSeedPhrase() {
// Фиксированная seed phrase для тестирования
val seedPhrase = listOf(
"abandon", "abandon", "abandon", "abandon", "abandon", "abandon",
"abandon", "abandon", "abandon", "abandon", "abandon", "about"
)
println("=== Crypto New Compatibility Test ===")
println("Seed phrase: ${seedPhrase.joinToString(" ")}")
println()
// Генерируем ключи
val keyPair = CryptoManager.generateKeyPairFromSeed(seedPhrase)
val privateKeyHash = CryptoManager.generatePrivateKeyHash(keyPair.privateKey)
// Выводим результаты
println("Android Results:")
println("Private Key: ${keyPair.privateKey}")
println("Public Key: ${keyPair.publicKey}")
println("Private Key Hash: $privateKeyHash")
println()
// Проверяем формат
assertEquals("Private key should be 64 hex chars (32 bytes)", 64, keyPair.privateKey.length)
assertEquals("Public key should be 66 hex chars (33 bytes compressed)", 66, keyPair.publicKey.length)
assertEquals("Private key hash should be 64 hex chars", 64, privateKeyHash.length)
// Проверяем что публичный ключ сжатый (начинается с 02 или 03)
assertTrue(
"Public key should start with 02 or 03 (compressed format)",
keyPair.publicKey.startsWith("02") || keyPair.publicKey.startsWith("03")
)
println("✅ Format checks passed!")
println()
println("Now run this in JavaScript (crypto_new/crypto.ts):")
println("```javascript")
println("const { generateKeyPairFromSeed, generateHashFromPrivateKey } = require('./crypto');")
println("const seedPhrase = '${seedPhrase.joinToString(" ")}';")
println("const keyPair = await generateKeyPairFromSeed(seedPhrase);")
println("const hash = await generateHashFromPrivateKey(keyPair.privateKey);")
println("console.log('Private Key:', keyPair.privateKey);")
println("console.log('Public Key:', keyPair.publicKey);")
println("console.log('Hash:', hash);")
println("```")
println()
println("Expected JavaScript results:")
println("Private Key: ${keyPair.privateKey}")
println("Public Key: ${keyPair.publicKey}")
println("Hash: $privateKeyHash")
}
@Test
fun testMultipleSeedPhrases() {
val testCases = listOf(
listOf("test", "seed", "phrase", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"),
listOf("hello", "world", "crypto", "test", "android", "kotlin", "secp256k1", "sha256", "compressed", "public", "key", "format"),
listOf("abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "about")
)
println("=== Multiple Seed Phrases Test ===")
testCases.forEachIndexed { index, seedPhrase ->
println("Test case ${index + 1}:")
println("Seed: ${seedPhrase.joinToString(" ")}")
val keyPair = CryptoManager.generateKeyPairFromSeed(seedPhrase)
val hash = CryptoManager.generatePrivateKeyHash(keyPair.privateKey)
println("Private: ${keyPair.privateKey}")
println("Public: ${keyPair.publicKey}")
println("Hash: $hash")
// Verify format
assertEquals(64, keyPair.privateKey.length)
assertEquals(66, keyPair.publicKey.length)
assertTrue(keyPair.publicKey.startsWith("02") || keyPair.publicKey.startsWith("03"))
println("✅ Passed")
println()
}
}
@Test
fun testPrivateKeyHashGeneration() {
val privateKey = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
val hash = CryptoManager.generatePrivateKeyHash(privateKey)
println("=== Private Key Hash Test ===")
println("Private Key: $privateKey")
println("Hash (Android): $hash")
println()
println("JavaScript equivalent:")
println("```javascript")
println("const privateKey = '$privateKey';")
println("const hash = sha256.create().update(privateKey + 'rosetta').digest().toHex().toString();")
println("console.log('Hash (JS):', hash);")
println("```")
println()
println("Hashes should match!")
assertEquals(64, hash.length)
}
@Test
fun testPublicKeyCompression() {
// Тестируем что все публичные ключи действительно сжаты
val seedPhrases = listOf(
listOf("word", "word", "word", "word", "word", "word", "word", "word", "word", "word", "word", "word"),
listOf("test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test"),
listOf("crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto")
)
println("=== Public Key Compression Test ===")
seedPhrases.forEach { seedPhrase ->
val keyPair = CryptoManager.generateKeyPairFromSeed(seedPhrase)
// Проверяем что ключ сжатый (33 байта = 66 hex chars)
assertEquals("Public key must be compressed (33 bytes)", 66, keyPair.publicKey.length)
// Проверяем префикс (02 для четного Y, 03 для нечетного Y)
val prefix = keyPair.publicKey.substring(0, 2)
assertTrue(
"Compressed public key must start with 02 or 03",
prefix == "02" || prefix == "03"
)
println("${seedPhrase.joinToString(" ")}: ${keyPair.publicKey}")
}
println()
println("✅ All public keys are compressed!")
}
@Test
fun testCachingMechanism() {
val seedPhrase = listOf("cache", "test", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten")
println("=== Caching Test ===")
// Первый вызов - генерация
val start1 = System.currentTimeMillis()
val keyPair1 = CryptoManager.generateKeyPairFromSeed(seedPhrase)
val time1 = System.currentTimeMillis() - start1
// Второй вызов - из кэша
val start2 = System.currentTimeMillis()
val keyPair2 = CryptoManager.generateKeyPairFromSeed(seedPhrase)
val time2 = System.currentTimeMillis() - start2
println("First call (generation): ${time1}ms")
println("Second call (from cache): ${time2}ms")
println("Speedup: ${time1.toFloat() / time2.toFloat()}x")
// Проверяем что результаты идентичны
assertEquals(keyPair1.privateKey, keyPair2.privateKey)
assertEquals(keyPair1.publicKey, keyPair2.publicKey)
println("✅ Cache is working correctly!")
}
}