signature: forbid sending message if key is close to expiring

This commit is contained in:
Bixilon 2023-01-28 17:42:04 +01:00
parent caac1d5722
commit 4d58b71673
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
3 changed files with 32 additions and 5 deletions

View File

@ -17,4 +17,6 @@ object ChatSignatureProperties {
const val MESSAGE_TTL = 2 * 60 * 1000 // 2 Minutes
const val MESSAGE_TTL_LONG = 5 * 60 * 1000 // 5 Minutes
const val SIGNATURE_SIZE = 256
const val MINIMUM_KEY_TTL = MESSAGE_TTL_LONG
}

View File

@ -0,0 +1,20 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.chat.signature.errors
import de.bixilon.minosoft.data.entities.entities.player.local.PlayerPrivateKey
class KeyExpiredError(
val key: PlayerPrivateKey,
) : Exception("Your private key is expired or is near its end!")

View File

@ -21,8 +21,11 @@ import de.bixilon.minosoft.data.chat.ChatUtil
import de.bixilon.minosoft.data.chat.message.internal.DebugChatMessage
import de.bixilon.minosoft.data.chat.message.internal.InternalChatMessage
import de.bixilon.minosoft.data.chat.signature.Acknowledgement
import de.bixilon.minosoft.data.chat.signature.ChatSignatureProperties.MINIMUM_KEY_TTL
import de.bixilon.minosoft.data.chat.signature.errors.KeyExpiredError
import de.bixilon.minosoft.data.chat.signature.signer.MessageSigner
import de.bixilon.minosoft.data.entities.entities.player.local.HealthCondition
import de.bixilon.minosoft.data.entities.entities.player.local.PlayerPrivateKey
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.world.time.WorldTime
import de.bixilon.minosoft.data.world.weather.WorldWeather
@ -37,7 +40,6 @@ import de.bixilon.minosoft.protocol.packets.c2s.play.chat.CommandC2SP
import de.bixilon.minosoft.protocol.packets.c2s.play.chat.SignedChatMessageC2SP
import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogMessageType
import java.security.PrivateKey
import java.security.SecureRandom
import java.time.Instant
@ -68,7 +70,7 @@ class ConnectionUtil(
return
}
Log.log(LogMessageType.CHAT_OUT) { trimmed }
val privateKey = connection.player.privateKey?.private
val privateKey = connection.player.privateKey
if (!connection.version.requiresSignedChat) {
return connection.sendPacket(ChatMessageC2SP(trimmed))
}
@ -78,15 +80,18 @@ class ConnectionUtil(
sendSignedMessage(privateKey, trimmed)
}
fun sendSignedMessage(privateKey: PrivateKey = connection.player.privateKey!!.private, message: String) {
val salt = random.nextLong()
fun sendSignedMessage(privateKey: PlayerPrivateKey = connection.player.privateKey!!, message: String) {
val time = Instant.now()
if (time.isAfter(privateKey.expiresAt.minusMillis(MINIMUM_KEY_TTL.toLong()))) {
throw KeyExpiredError(privateKey)
}
val salt = random.nextLong()
val uuid = connection.player.uuid
val acknowledgement = Acknowledgement.EMPTY
val signature: ByteArray? = if (connection.network.encrypted) {
signer.signMessage(privateKey, message, null, salt, uuid, time, acknowledgement.lastSeen)
signer.signMessage(privateKey.private, message, null, salt, uuid, time, acknowledgement.lastSeen)
} else {
null
}