feat: Update authorization logic for compatibility with crypto_new; enhance key generation and public key format
This commit is contained in:
@@ -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!")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user