adopted crypto2 0.4.*
This commit is contained in:
parent
38fbca955c
commit
5df6143c75
@ -44,6 +44,7 @@ kotlin {
|
||||
// iosArm64()
|
||||
// iosSimulatorArm64()
|
||||
linuxX64()
|
||||
linuxArm64()
|
||||
// macosX64()
|
||||
|
||||
|
||||
@ -66,7 +67,7 @@ kotlin {
|
||||
|
||||
// api("net.sergeych:mp_bintools:0.1.1")
|
||||
// api("net.sergeych:mp_stools:1.4.7")
|
||||
api("net.sergeych:crypto2:0.2.2-SNAPSHOT")
|
||||
api("net.sergeych:crypto2:0.4.1-SNAPSHOT")
|
||||
}
|
||||
}
|
||||
val commonTest by getting {
|
||||
|
@ -9,6 +9,7 @@ import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import net.sergeych.crypto2.SigningKey
|
||||
import net.sergeych.crypto2.VerifyingPublicKey
|
||||
import net.sergeych.mp_logger.LogTag
|
||||
import net.sergeych.mp_logger.Loggable
|
||||
import net.sergeych.mp_logger.debug
|
||||
@ -23,7 +24,7 @@ import net.sergeych.mp_tools.globalLaunch
|
||||
*/
|
||||
class KiloClient<S>(
|
||||
localInterface: KiloInterface<S>,
|
||||
secretKey: SigningKey.Secret? = null,
|
||||
secretKey: SigningKey? = null,
|
||||
connectionDataFactory: ConnectionDataFactory<S>,
|
||||
) : RemoteInterface,
|
||||
Loggable by LogTag("CLIF") {
|
||||
@ -101,14 +102,14 @@ class KiloClient<S>(
|
||||
suspend fun token() = deferredClient.await().token()
|
||||
|
||||
/**
|
||||
* Remote party shared key ([SigningKey.Public]]), could be used ti ensure server is what we expected and
|
||||
* Remote party shared key ([VerifyingPublicKey]), could be used ti ensure server is what we expected and
|
||||
* there is no active MITM attack.
|
||||
*
|
||||
* Non-null value means the key was successfully authenticated, null means remote party did not provide
|
||||
* a key. Connection is established either with a properly authenticated key or no key at all.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
suspend fun remoteId() = deferredClient.await().remoteId()
|
||||
suspend fun remoteId(): VerifyingPublicKey? = deferredClient.await().remoteId()
|
||||
|
||||
companion object {
|
||||
class Builder<S>() {
|
||||
@ -120,7 +121,7 @@ class KiloClient<S>(
|
||||
}
|
||||
private var connectionBuilder: (suspend () -> Transport.Device)? = null
|
||||
|
||||
var secretIdKey: SigningKey.Secret? = null
|
||||
var secretIdKey: SigningKey? = null
|
||||
|
||||
/**
|
||||
* Build local command implementations (remotely callable ones), exception
|
||||
|
@ -3,6 +3,7 @@ package net.sergeych.kiloparsec
|
||||
import kotlinx.coroutines.*
|
||||
import net.sergeych.crypto2.SafeKeyExchange
|
||||
import net.sergeych.crypto2.SigningKey
|
||||
import net.sergeych.crypto2.VerifyingPublicKey
|
||||
import net.sergeych.mp_logger.LogTag
|
||||
import net.sergeych.mp_logger.Loggable
|
||||
import net.sergeych.mp_logger.debug
|
||||
@ -15,17 +16,17 @@ class KiloClientConnection<S>(
|
||||
private val clientInterface: KiloInterface<S>,
|
||||
private val device: Transport.Device,
|
||||
private val session: S,
|
||||
private val secretIdKey: SigningKey.Secret? = null,
|
||||
private val secretIdKey: SigningKey? = null,
|
||||
) : RemoteInterface, Loggable by LogTag("KPC:${++clientIds}") {
|
||||
|
||||
constructor(localInterface: KiloInterface<S>, connection: KiloConnectionData<S>, secretIdKey: SigningKey.Secret? = null)
|
||||
constructor(localInterface: KiloInterface<S>, connection: KiloConnectionData<S>, secretIdKey: SigningKey? = null)
|
||||
: this(localInterface, connection.device, connection.session, secretIdKey)
|
||||
|
||||
private val kiloRemoteInterface = CompletableDeferred<KiloRemoteInterface<S>>()
|
||||
|
||||
private val deferredParams = CompletableDeferred<KiloParams<S>>()
|
||||
|
||||
suspend fun remoteId(): SigningKey.Public? = deferredParams.await().remoteIdentity
|
||||
suspend fun remoteId(): VerifyingPublicKey? = deferredParams.await().remoteIdentity
|
||||
|
||||
/**
|
||||
* Run the client, blocking until the device is closed, or some critical exception
|
||||
@ -69,7 +70,7 @@ class KiloClientConnection<S>(
|
||||
L0ClientId, params.encrypt(
|
||||
pack(
|
||||
ClientIdentity(
|
||||
secretIdKey?.publicKey,
|
||||
secretIdKey?.verifyingKey,
|
||||
secretIdKey?.sign(params.token)
|
||||
)
|
||||
)
|
||||
|
@ -24,7 +24,7 @@ data class KiloParams<S>(
|
||||
val transport: RemoteInterface,
|
||||
val sessionKey: SafeKeyExchange.SessionKey,
|
||||
val scopeSession: S,
|
||||
val remoteIdentity: SigningKey.Public?,
|
||||
val remoteIdentity: VerifyingPublicKey?,
|
||||
val remoteTransport: RemoteInterface,
|
||||
) {
|
||||
@Serializable
|
||||
@ -41,12 +41,12 @@ data class KiloParams<S>(
|
||||
override val session = scopeSession
|
||||
override val remote: RemoteInterface = remoteTransport
|
||||
override val sessionToken: UByteArray = token
|
||||
override val remoteIdentity: SigningKey.Public? = this@KiloParams.remoteIdentity
|
||||
override val remoteIdentity: VerifyingPublicKey? = this@KiloParams.remoteIdentity
|
||||
}
|
||||
}
|
||||
|
||||
val token: UByteArray by lazy {
|
||||
blake2b("token_".encodeToUByteArray() + sessionKey.sessionTag).sliceArray(0..<SymmetricKey.nonceByteLength)
|
||||
blake2b("token_".encodeToUByteArray() + sessionKey.sessionTag).sliceArray(0..<SymmetricKey.nonceLength)
|
||||
}
|
||||
|
||||
private val numericNonce = NumericNonce(token)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.sergeych.kiloparsec
|
||||
|
||||
import net.sergeych.crypto2.SigningKey
|
||||
import net.sergeych.crypto2.VerifyingPublicKey
|
||||
|
||||
/**
|
||||
* Scope for Kiloparsec client/server commands execution, contain per-connection specific data. The scope
|
||||
@ -26,8 +27,8 @@ interface KiloScope<S> {
|
||||
val sessionToken: UByteArray
|
||||
|
||||
/**
|
||||
* If the remote part has provided a secret key, e.g., gave non-null [SigningKey.Secret] on construction,
|
||||
* the kiloparsec checks it in the MITM-safe way and provides its [SigningKey.Public] shared key here.
|
||||
* If the remote part has provided a secret key, e.g., gave non-null [SigningKey] on construction,
|
||||
* the kiloparsec checks it in the MITM-safe way and provides its [VerifyingPublicKey] shared key here.
|
||||
* Knowing a remote party shared key, it is possible to be sure that the connection is made directly
|
||||
* to this party with no middle point intruders.
|
||||
*
|
||||
@ -37,6 +38,6 @@ interface KiloScope<S> {
|
||||
* In spite of the above said, which means, non-null value in this field means the key is authorized, but
|
||||
* It is up to the caller to ensure it is expected key of the remote party.
|
||||
*/
|
||||
val remoteIdentity: SigningKey.Public?
|
||||
val remoteIdentity: VerifyingPublicKey?
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ private val instances = AtomicCounter()
|
||||
class KiloServer<S>(
|
||||
private val clientInterface: KiloInterface<S>,
|
||||
private val connections: Flow<InetTransportDevice>,
|
||||
private val serverSecretKey: SigningKey.Secret? = null,
|
||||
private val serverSecretKey: SigningKey? = null,
|
||||
private val sessionBuilder: ()->S,
|
||||
): LogTag("KS:${instances.incrementAndGet()}") {
|
||||
|
||||
|
@ -23,14 +23,14 @@ class KiloServerConnection<S>(
|
||||
private val clientInterface: KiloInterface<S>,
|
||||
private val device: Transport.Device,
|
||||
private val session: S,
|
||||
private val serverSigningKey: SigningKey.Secret? = null
|
||||
private val serverSigningKey: SigningKey? = null
|
||||
) : RemoteInterface, Loggable by LogTag("SRV${++serverIds}") {
|
||||
|
||||
/**
|
||||
* Shortcut to construct with [KiloConnectionData] intance
|
||||
*/
|
||||
@Suppress("unused")
|
||||
constructor(localInterface: KiloInterface<S>, connection: KiloConnectionData<S>, serverSecretKey: SigningKey.Secret? = null)
|
||||
constructor(localInterface: KiloInterface<S>, connection: KiloConnectionData<S>, serverSecretKey: SigningKey? = null)
|
||||
: this(localInterface, connection.device, connection.session, serverSecretKey)
|
||||
|
||||
private val kiloRemoteInterface = CompletableDeferred<KiloRemoteInterface<S>>()
|
||||
|
@ -28,7 +28,7 @@ fun <S> websocketClient(
|
||||
path: String,
|
||||
clientInterface: KiloInterface<S> = KiloInterface(),
|
||||
client: HttpClient = HttpClient { install(WebSockets) },
|
||||
secretKey: SigningKey.Secret? = null,
|
||||
secretKey: SigningKey? = null,
|
||||
sessionMaker: () -> S = {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
Unit as S
|
||||
|
@ -3,7 +3,7 @@ package net.sergeych.kiloparsec
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.sergeych.crypto2.SafeKeyExchange
|
||||
import net.sergeych.crypto2.Seal
|
||||
import net.sergeych.crypto2.SigningKey
|
||||
import net.sergeych.crypto2.VerifyingPublicKey
|
||||
|
||||
// L0 commands - key exchange and check:
|
||||
@Serializable
|
||||
@ -11,7 +11,7 @@ data class Handshake(val version: UInt, val publicKey: SafeKeyExchange.PublicKey
|
||||
val signature: Seal? = null)
|
||||
|
||||
@Serializable
|
||||
data class ClientIdentity(val clientIdKey: SigningKey.Public?, val signature: UByteArray?)
|
||||
data class ClientIdentity(val clientIdKey: VerifyingPublicKey?, val signature: UByteArray?)
|
||||
|
||||
// Level 0 command: request key exchange
|
||||
internal val L0Request by command<Handshake, Handshake>()
|
||||
|
@ -1,5 +1,8 @@
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.sergeych.crypto2.*
|
||||
import net.sergeych.crypto2.IllegalSignatureException
|
||||
import net.sergeych.crypto2.SealedBox
|
||||
import net.sergeych.crypto2.SigningSecretKey
|
||||
import net.sergeych.crypto2.initCrypto
|
||||
import net.sergeych.kiloparsec.encodeToUByteArray
|
||||
import net.sergeych.utools.pack
|
||||
import net.sergeych.utools.unpack
|
||||
@ -9,11 +12,11 @@ class KeysTest {
|
||||
@Test
|
||||
fun testCreationAndMap() = runTest {
|
||||
initCrypto()
|
||||
val (stk,pbk) = SigningKey.pair()
|
||||
val (stk,pbk) = SigningSecretKey.generatePair()
|
||||
|
||||
val x = mapOf( stk to "STK!", pbk to "PBK!")
|
||||
assertEquals("STK!", x[stk])
|
||||
val s1 = SigningKey.Secret(stk.packed)
|
||||
val s1 = SigningSecretKey(stk.keyBytes)
|
||||
assertEquals(stk, s1)
|
||||
assertEquals("STK!", x[s1])
|
||||
assertEquals("PBK!", x[pbk])
|
||||
@ -25,8 +28,8 @@ class KeysTest {
|
||||
|
||||
data1[0] = 0x01u
|
||||
assertFalse(s.isValid(data1))
|
||||
val p2 = SigningKey.pair()
|
||||
val p3 = SigningKey.pair()
|
||||
val p2 = SigningSecretKey.generatePair()
|
||||
val p3 = SigningSecretKey.generatePair()
|
||||
|
||||
val ms = SealedBox(data, s1) + p2.secretKey
|
||||
|
||||
|
@ -1,23 +1,4 @@
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.sergeych.crypto2.createContrail
|
||||
import net.sergeych.crypto2.initCrypto
|
||||
import net.sergeych.crypto2.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) }
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun testRemoceCmd() {
|
||||
// assertEquals("lalala", removeCmd("lalala"))
|
||||
|
@ -3,7 +3,8 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.channels.SendChannel
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.sergeych.crypto2.SigningKey
|
||||
import net.sergeych.crypto2.SigningSecretKey
|
||||
import net.sergeych.crypto2.VerifyingPublicKey
|
||||
import net.sergeych.crypto2.initCrypto
|
||||
import net.sergeych.kiloparsec.*
|
||||
import net.sergeych.mp_logger.Log
|
||||
@ -167,7 +168,7 @@ class TransportTest {
|
||||
val cmdPing by command<String, String>()
|
||||
val cmdPush by command<String, String>()
|
||||
val cmdGetToken by command<Unit, UByteArray>()
|
||||
val cmdGetClientId by command<Unit, SigningKey.Public?>()
|
||||
val cmdGetClientId by command<Unit, VerifyingPublicKey?>()
|
||||
val cmdChainCallServer1 by command<String, String>()
|
||||
val cmdChainCallClient1 by command<String, String>()
|
||||
val cmdChainCallServer2 by command<String, String>()
|
||||
@ -176,8 +177,8 @@ class TransportTest {
|
||||
// Log.defaultLevel = Log.Level.DEBUG
|
||||
val (d1, d2) = createTestDevice()
|
||||
|
||||
val serverId = SigningKey.pair()
|
||||
val clientId = SigningKey.pair()
|
||||
val serverId = SigningSecretKey.generatePair()
|
||||
val clientId = SigningSecretKey.generatePair()
|
||||
|
||||
val cmdException by command<Unit, Unit>()
|
||||
val cmdRemoteExceptionTest by command<Unit, String>()
|
||||
|
@ -21,7 +21,7 @@ import java.time.Duration
|
||||
fun <S> Application.setupWebsocketServer(
|
||||
localInterface: KiloInterface<S>,
|
||||
path: String = "/kp",
|
||||
serverKey: SigningKey.Secret? = null,
|
||||
serverKey: SigningKey? = null,
|
||||
createSession: () -> S,
|
||||
) {
|
||||
|
||||
|
@ -4,12 +4,12 @@ import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.ClosedReceiveChannelException
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import net.sergeych.crypto2.Contrail
|
||||
import net.sergeych.crypto2.encodeVarUnsigned
|
||||
import net.sergeych.crypto2.readVarUnsigned
|
||||
import net.sergeych.kiloparsec.RemoteInterface
|
||||
import net.sergeych.kiloparsec.Transport
|
||||
import net.sergeych.mp_logger.LogTag
|
||||
import net.sergeych.mp_logger.info
|
||||
import net.sergeych.mp_logger.warning
|
||||
import net.sergeych.mp_tools.globalLaunch
|
||||
import net.sergeych.tools.waitFor
|
||||
@ -25,7 +25,10 @@ private val log = LogTag("ASTD")
|
||||
/**
|
||||
* Prepend block with its size, varint-encoded
|
||||
*/
|
||||
private fun encode(block: UByteArray): ByteArray = (encodeVarUnsigned(block.size.toUInt()) + block).toByteArray()
|
||||
private fun encode(block: UByteArray): ByteArray {
|
||||
val c = Contrail.create(block)
|
||||
return (encodeVarUnsigned(c.size.toUInt()) + c).toByteArray()
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert asynchronous socket to a [Transport.Device] using non-blocking nio,
|
||||
@ -122,7 +125,8 @@ suspend fun asyncSocketToDevice(socket: AsynchronousSocketChannel): InetTranspor
|
||||
for (i in 0..<size.toInt()) {
|
||||
block[i] = input.receive()
|
||||
}
|
||||
inputBlocks.send(block)
|
||||
Contrail.unpack(block)?.let { inputBlocks.send(it) }
|
||||
?: log.warning { "skipping bad block ${block.size} bytes" }
|
||||
}
|
||||
}
|
||||
} catch (_: CancellationException) {
|
||||
@ -135,17 +139,13 @@ suspend fun asyncSocketToDevice(socket: AsynchronousSocketChannel): InetTranspor
|
||||
val addr = socket.remoteAddress as InetSocketAddress
|
||||
deferredDevice.complete(
|
||||
InetTransportDevice(inputBlocks, outputBlocks, JvmNetworkAddress(addr.address, addr.port), {
|
||||
val log = LogTag("S:${addr.address}:${addr.port}")
|
||||
log.info { "ASTD is waitig to close" }
|
||||
yield()
|
||||
// wait until all received data are parsed, but not too long
|
||||
withTimeoutOrNull(500) {
|
||||
receiving.waitFor { !it }
|
||||
}
|
||||
// then stop it
|
||||
log.info { "ASTd is calling STOP" }
|
||||
stop()
|
||||
log.info { "STopped" }
|
||||
})
|
||||
)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user