initial commit (moved from divan)
This commit is contained in:
commit
770555024f
56 files changed
+2745
No files matched your search
@@ -0,0 +1,58 @@
|
||||
import com.ionspin.kotlin.crypto.secretbox.SecretBox
|
||||
import com.ionspin.kotlin.crypto.util.decodeFromUByteArray
|
||||
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.sergeych.crypto.*
|
||||
import net.sergeych.utools.pack
|
||||
import net.sergeych.utools.unpack
|
||||
import kotlin.test.*
|
||||
|
||||
class KeysTest {
|
||||
@Test
|
||||
fun testCreationAndMap() = runTest {
|
||||
initCrypto()
|
||||
val (stk,pbk) = Key.Signing.pair()
|
||||
|
||||
val x = mapOf( stk to "STK!", pbk to "PBK!")
|
||||
assertEquals("STK!", x[stk])
|
||||
val s1 = Key.Signing(stk.packed)
|
||||
assertEquals(stk, s1)
|
||||
assertEquals("STK!", x[s1])
|
||||
assertEquals("PBK!", x[pbk])
|
||||
|
||||
val data = "8 rays dev!".encodeToUByteArray()
|
||||
val data1 = "8 rays dev!".encodeToUByteArray()
|
||||
val s = SignedBox.Seal.create(stk, data)
|
||||
assertTrue(s.verify(data))
|
||||
|
||||
data1[0] = 0x01u
|
||||
assertFalse(s.verify(data1))
|
||||
val p2 = Key.Signing.pair()
|
||||
val p3 = Key.Signing.pair()
|
||||
|
||||
val ms = SignedBox(data, s1) + p2.signing
|
||||
|
||||
// non tampered:
|
||||
val ms1 = unpack<SignedBox>(pack(ms))
|
||||
assertContentEquals(data, ms1.message)
|
||||
assertTrue(pbk in ms1)
|
||||
assertTrue(p2.verifying in ms1)
|
||||
assertTrue(p3.verifying !in ms1)
|
||||
|
||||
assertThrows<IllegalSignatureException> {
|
||||
unpack<SignedBox>(pack(ms).also { it[3] = 1u })
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun secretEncryptTest() = runTest {
|
||||
initCrypto()
|
||||
val key = SecretBox.keygen()
|
||||
val key1 = SecretBox.keygen()
|
||||
assertEquals("hello", decrypt(key, encrypt(key, "hello".encodeToUByteArray())).decodeFromUByteArray())
|
||||
assertThrows<DecryptionFailedException> {
|
||||
decrypt(key, encrypt(key1, "hello".encodeToUByteArray())).decodeFromUByteArray()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.datetime.Instant
|
||||
import net.sergeych.crypto.initCrypto
|
||||
import net.sergeych.kiloparsec.Transport
|
||||
import net.sergeych.utools.nowToSeconds
|
||||
import net.sergeych.utools.pack
|
||||
import net.sergeych.utools.unpack
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.time.Duration.Companion.microseconds
|
||||
|
||||
class PackTest {
|
||||
inline fun <reified T>check(x: T?) {
|
||||
assertEquals(x, unpack<T>(pack(x)))
|
||||
}
|
||||
@Test
|
||||
fun testNullPack() = runTest {
|
||||
initCrypto()
|
||||
val d = pack("Hello")
|
||||
assertEquals(6, d.size)
|
||||
check(1)
|
||||
check(2L)
|
||||
check(1.00)
|
||||
check("hello")
|
||||
check<String>(null)
|
||||
check<Long?>(null)
|
||||
}
|
||||
@Test
|
||||
fun testTimePack() = runTest {
|
||||
initCrypto()
|
||||
val t1 = nowToSeconds()
|
||||
val t2 = t1 + 1.microseconds
|
||||
assertEquals(t1, unpack<Instant>(pack(t2)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun packBlocks() {
|
||||
val b1 = Transport.Block.Call(1u, "foobar", ubyteArrayOf(1u,2u,3u))
|
||||
val p1 = pack(b1 as Transport.Block)
|
||||
val b2 = unpack<Transport.Block>(p1)
|
||||
assertEquals(b1,b2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.sergeych.crypto.createContrail
|
||||
import net.sergeych.crypto.initCrypto
|
||||
import net.sergeych.crypto.isValidContrail
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ToolsTest {
|
||||
@Test
|
||||
fun testContrails() = runTest {
|
||||
initCrypto()
|
||||
val c = createContrail(ubyteArrayOf(1u, 2u, 3u, 4u, 5u))
|
||||
assertEquals(134u, c[0])
|
||||
assertTrue { isValidContrail(c) }
|
||||
c[2] = 11u
|
||||
assertFalse { isValidContrail(c) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
import com.ionspin.kotlin.crypto.keyexchange.KeyExchange
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.channels.SendChannel
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.sergeych.crypto.Key
|
||||
import net.sergeych.crypto.initCrypto
|
||||
import net.sergeych.kiloparsec.command
|
||||
import net.sergeych.kiloparsec.*
|
||||
import net.sergeych.mp_logger.Log
|
||||
import kotlin.test.*
|
||||
|
||||
private var dcnt = 0
|
||||
fun createTestDevice(): Pair<Transport.Device, Transport.Device> {
|
||||
val p1 = Channel<UByteArray>(256)
|
||||
val p2 = Channel<UByteArray>(256)
|
||||
val id = ++dcnt
|
||||
val d1 = object : Transport.Device {
|
||||
override val input: ReceiveChannel<UByteArray?> = p1
|
||||
override val output: SendChannel<UByteArray> = p2
|
||||
override suspend fun close() {
|
||||
p2.close()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "D1:$id"
|
||||
}
|
||||
}
|
||||
val d2 = object : Transport.Device {
|
||||
override val input: ReceiveChannel<UByteArray?> = p2
|
||||
override val output: SendChannel<UByteArray> = p1
|
||||
override suspend fun close() {
|
||||
p1.close()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "D2:$id"
|
||||
}
|
||||
}
|
||||
return d1 to d2
|
||||
}
|
||||
|
||||
class TransportTest {
|
||||
|
||||
|
||||
@Test
|
||||
fun testTransportL0AndEncryption() = runTest {
|
||||
initCrypto()
|
||||
val cmdPing by command<String, String>()
|
||||
val cmdSlow by command<String, String>()
|
||||
|
||||
Log.connectConsole()
|
||||
Log.defaultLevel = Log.Level.DEBUG
|
||||
val (d1, d2) = createTestDevice()
|
||||
val l1 = LocalInterface<Unit>().apply {
|
||||
on(cmdPing) {
|
||||
"p1: $it"
|
||||
}
|
||||
}
|
||||
val l2 = LocalInterface<Unit>().apply {
|
||||
on(cmdPing) {
|
||||
"p2: $it"
|
||||
}
|
||||
on(cmdSlow) {
|
||||
delay(100)
|
||||
"done"
|
||||
}
|
||||
}
|
||||
val t1 = Transport(d1, l1, Unit)
|
||||
val t2 = Transport(d2, l2, Unit)
|
||||
|
||||
val clip = KeyExchange.keypair()
|
||||
val serp = KeyExchange.keypair()
|
||||
val clisk = KeyExchange.clientSessionKeys(clip.publicKey, clip.secretKey, serp.publicKey)
|
||||
val sersk = KeyExchange.serverSessionKeys(serp.publicKey, serp.secretKey, clip.publicKey)
|
||||
val pser = KiloParams(true, t1, sersk, Unit, null, t1)
|
||||
val pcli = KiloParams(false, t2, clisk, Unit, null, t2)
|
||||
|
||||
assertContentEquals(pcli.token, pser.token)
|
||||
assertEquals(pser.decryptString(pcli.encrypt("hello!")), "hello!")
|
||||
assertEquals(pser.decryptString(pcli.encrypt("hello!")), "hello!")
|
||||
assertEquals(pser.decryptString(pcli.encrypt("hello2!")), "hello2!")
|
||||
assertEquals(pser.decryptString(pcli.encrypt("hello3!")), "hello3!")
|
||||
assertEquals(pser.decryptString(pcli.encrypt("hello!")), "hello!")
|
||||
|
||||
// test nonce increment
|
||||
assertFalse { pcli.encrypt("once") contentEquals pcli.encrypt("once") }
|
||||
|
||||
assertEquals(pcli.decryptString(pser.encrypt("hello!")), "hello!")
|
||||
assertEquals(pcli.decryptString(pser.encrypt("hello!")), "hello!")
|
||||
assertEquals(pcli.decryptString(pser.encrypt("hello!")), "hello!")
|
||||
assertEquals(pcli.decryptString(pser.encrypt("hello!")), "hello!")
|
||||
assertEquals(pcli.decryptString(pser.encrypt("hello!")), "hello!")
|
||||
assertEquals(pcli.decryptString(pser.encrypt("hello!")), "hello!")
|
||||
|
||||
|
||||
coroutineScope {
|
||||
val j1 = launch { t1.run() }
|
||||
val j2 = launch { t2.run() }
|
||||
launch {
|
||||
assertThrows<RemoteInterface.ClosedException> {
|
||||
t1.call(cmdSlow, "foo1")
|
||||
}
|
||||
}
|
||||
assertEquals("p2: foo", t1.call(cmdPing, "foo"))
|
||||
assertEquals("p1: bar", t2.call(cmdPing, "bar"))
|
||||
assertEquals("p2: foo", t1.call(cmdPing, "foo"))
|
||||
j1.cancelAndJoin()
|
||||
j2.cancelAndJoin()
|
||||
}
|
||||
d1.close()
|
||||
d2.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testConnection() = runTest {
|
||||
initCrypto()
|
||||
|
||||
val cmdPing by command<String, String>()
|
||||
val cmdPush by command<String, String>()
|
||||
val cmdGetToken by command<Unit, UByteArray>()
|
||||
Log.connectConsole()
|
||||
// Log.defaultLevel = Log.Level.DEBUG
|
||||
val (d1, d2) = createTestDevice()
|
||||
val serverInterface = KiloInterface<String>().apply {
|
||||
on(cmdPing) {
|
||||
"pong! [$it]"
|
||||
}
|
||||
on(cmdGetToken) {
|
||||
sessionToken
|
||||
}
|
||||
registerError { IllegalStateException() }
|
||||
registerError { IllegalArgumentException(it) }
|
||||
}
|
||||
val kiloServerConnection = KiloServerConnection(serverInterface, d1, "server session")
|
||||
launch { kiloServerConnection.run() }
|
||||
|
||||
val clientInterface = KiloInterface<String>().apply {
|
||||
on(cmdPush) {
|
||||
"server push: $it"
|
||||
}
|
||||
on(cmdPing) {
|
||||
"client pong: $it"
|
||||
}
|
||||
}
|
||||
val client = KiloClientConnection(clientInterface, d2, "client session")
|
||||
launch { client.run() }
|
||||
assertEquals("pong! [hello]", client.call(cmdPing, "hello"))
|
||||
assertEquals("pong! [foo]", client.call(cmdPing, "foo"))
|
||||
assertEquals("client pong: foo", kiloServerConnection.call(cmdPing, "foo"))
|
||||
assertEquals("server push: bar", kiloServerConnection.call(cmdPush, "bar"))
|
||||
|
||||
assertContentEquals(client.token(), client.call(cmdGetToken))
|
||||
d1.close()
|
||||
d2.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClient() = runTest {
|
||||
initCrypto()
|
||||
|
||||
val cmdPing by command<String, String>()
|
||||
val cmdPush by command<String, String>()
|
||||
val cmdGetToken by command<Unit, UByteArray>()
|
||||
val cmdGetClientId by command<Unit, Key.Verifying?>()
|
||||
val cmdChainCallServer1 by command<String, String>()
|
||||
val cmdChainCallClient1 by command<String, String>()
|
||||
val cmdChainCallServer2 by command<String, String>()
|
||||
val cmdChainCallClient2 by command<String, String>()
|
||||
Log.connectConsole()
|
||||
// Log.defaultLevel = Log.Level.DEBUG
|
||||
val (d1, d2) = createTestDevice()
|
||||
|
||||
val serverId = Key.Signing.pair()
|
||||
val clientId = Key.Signing.pair()
|
||||
|
||||
val serverInterface = KiloInterface<String>().apply {
|
||||
on(cmdPing) {
|
||||
"pong! [$it]"
|
||||
}
|
||||
on(cmdGetToken) {
|
||||
sessionToken
|
||||
}
|
||||
on(cmdGetClientId) {
|
||||
remoteIdentity
|
||||
}
|
||||
on(cmdChainCallServer1) {
|
||||
remote.call(cmdChainCallClient1, it + "-s1")
|
||||
}
|
||||
on(cmdChainCallServer2) {
|
||||
remote.call(cmdChainCallClient2, "$it-s2")
|
||||
}
|
||||
registerError { IllegalStateException() }
|
||||
registerError { IllegalArgumentException(it) }
|
||||
}
|
||||
val kiloServerConnection = KiloServerConnection(serverInterface, d1, "server session", serverId.signing)
|
||||
launch { kiloServerConnection.run() }
|
||||
|
||||
var cnt = 0
|
||||
val client = KiloClient {
|
||||
session { "client session!" }
|
||||
secretIdKey = clientId.signing
|
||||
local {
|
||||
on(cmdPush) {
|
||||
"server push: $it"
|
||||
}
|
||||
on(cmdPing) {
|
||||
"client pong: $it"
|
||||
}
|
||||
on(cmdChainCallClient1) {
|
||||
remote.call(cmdChainCallServer2,"$it-c1")
|
||||
}
|
||||
on(cmdChainCallClient2) { "$it-c2" }
|
||||
}
|
||||
connect {
|
||||
if (cnt++ > 0) {
|
||||
cancel()
|
||||
fail("connect called once again")
|
||||
}
|
||||
d2
|
||||
}
|
||||
}
|
||||
assertEquals("pong! [hello]", client.call(cmdPing, "hello"))
|
||||
assertEquals("pong! [foo]", client.call(cmdPing, "foo"))
|
||||
assertEquals("client pong: foo", kiloServerConnection.call(cmdPing, "foo"))
|
||||
assertEquals("server push: bar", kiloServerConnection.call(cmdPush, "bar"))
|
||||
|
||||
assertEquals("**-s1-c1-s2-c2", client.call(cmdChainCallServer1, "**"))
|
||||
d1.close()
|
||||
d2.close()
|
||||
client.close()
|
||||
// assertEquals(1, connectionCounter)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAuthentication() = runTest {
|
||||
initCrypto()
|
||||
|
||||
val cmdPing by command<String, String>()
|
||||
val cmdPush by command<String, String>()
|
||||
val cmdGetToken by command<Unit, UByteArray>()
|
||||
Log.connectConsole()
|
||||
Log.defaultLevel = Log.Level.DEBUG
|
||||
val (d1, d2) = createTestDevice()
|
||||
val serverInterface = KiloInterface<String>().apply {
|
||||
on(cmdPing) {
|
||||
"pong! [$it]"
|
||||
}
|
||||
on(cmdGetToken) {
|
||||
sessionToken
|
||||
}
|
||||
registerError { IllegalStateException() }
|
||||
registerError { IllegalArgumentException(it) }
|
||||
}
|
||||
val kiloServerConnection = KiloServerConnection(serverInterface, d1, "server session")
|
||||
launch { kiloServerConnection.run() }
|
||||
|
||||
var cnt = 0
|
||||
val client = KiloClient {
|
||||
session { "client session!" }
|
||||
local {
|
||||
on(cmdPush) {
|
||||
"server push: $it"
|
||||
}
|
||||
on(cmdPing) {
|
||||
"client pong: $it"
|
||||
}
|
||||
}
|
||||
connect {
|
||||
if (cnt++ > 0) {
|
||||
cancel()
|
||||
fail("connect called once again")
|
||||
}
|
||||
d2
|
||||
}
|
||||
}
|
||||
assertEquals("pong! [hello]", client.call(cmdPing, "hello"))
|
||||
assertEquals("pong! [foo]", client.call(cmdPing, "foo"))
|
||||
assertEquals("client pong: foo", kiloServerConnection.call(cmdPing, "foo"))
|
||||
assertEquals("server push: bar", kiloServerConnection.call(cmdPush, "bar"))
|
||||
|
||||
assertContentEquals(client.call(cmdGetToken), client.token())
|
||||
client.close()
|
||||
d1.close()
|
||||
d2.close()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import kotlin.test.fail
|
||||
|
||||
inline fun <reified T: Throwable>assertThrows(f: ()->Unit): T {
|
||||
val name = T::class.simpleName
|
||||
try {
|
||||
f()
|
||||
fail("expected to throw $name but threw nothing")
|
||||
}
|
||||
catch(x: Throwable) {
|
||||
if( x is T ) return x
|
||||
fail("expected to throw $name but instead threw ${x::class.simpleName}: $x")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user