diff --git a/login-server/pom.xml b/login-server/pom.xml index 33dd3ea..0c8ee7c 100644 --- a/login-server/pom.xml +++ b/login-server/pom.xml @@ -22,6 +22,11 @@ service-discovery ${project.version} + + com.password4j + password4j + ${password4j.version} + com.fasterxml.jackson.dataformat jackson-dataformat-toml diff --git a/login-server/src/main/kotlin/work/fking/pangya/login/auth/Authenticator.kt b/login-server/src/main/kotlin/work/fking/pangya/login/auth/Authenticator.kt index 532ea30..a82d3ad 100644 --- a/login-server/src/main/kotlin/work/fking/pangya/login/auth/Authenticator.kt +++ b/login-server/src/main/kotlin/work/fking/pangya/login/auth/Authenticator.kt @@ -4,10 +4,10 @@ package work.fking.pangya.login.auth val NOOP_AUTHENTICATOR: Authenticator = Authenticator { _, _ -> InvalidCredentialsResult } fun interface Authenticator { - fun authenticate(username: String, password: CharArray): AuthResult + fun authenticate(username: String, password: ByteArray): AuthResult } sealed interface AuthResult data class SuccessResult(val userInfo: UserInfo) : AuthResult data class ExceptionResult(val exception: Exception) : AuthResult -data object InvalidCredentialsResult : AuthResult +data object InvalidCredentialsResult : AuthResult \ No newline at end of file diff --git a/login-server/src/main/kotlin/work/fking/pangya/login/auth/DatabaseAuthenticator.kt b/login-server/src/main/kotlin/work/fking/pangya/login/auth/DatabaseAuthenticator.kt index 4ca8d30..1835c38 100644 --- a/login-server/src/main/kotlin/work/fking/pangya/login/auth/DatabaseAuthenticator.kt +++ b/login-server/src/main/kotlin/work/fking/pangya/login/auth/DatabaseAuthenticator.kt @@ -1,12 +1,18 @@ package work.fking.pangya.login.auth +import com.password4j.Password import work.fking.pangya.login.persistence.AccountRepository -class DatabaseAuthenticator(val repository: AccountRepository) : Authenticator { +class DatabaseAuthenticator( + private val repository: AccountRepository +) : Authenticator { - override fun authenticate(username: String, password: CharArray): AuthResult { - val userInfo = repository.loadUserInfo(username, password = ByteArray(0)) + override fun authenticate(username: String, password: ByteArray): AuthResult { + val userInfo = repository.loadUserInfo(username) ?: return InvalidCredentialsResult - return userInfo?.let { SuccessResult(it) } ?: InvalidCredentialsResult + if (Password.check(password, userInfo.password).withBcrypt()) { + return SuccessResult(userInfo) + } + return InvalidCredentialsResult } } \ No newline at end of file diff --git a/login-server/src/main/kotlin/work/fking/pangya/login/auth/UserInfo.kt b/login-server/src/main/kotlin/work/fking/pangya/login/auth/UserInfo.kt index 1a6a6f4..c102d52 100644 --- a/login-server/src/main/kotlin/work/fking/pangya/login/auth/UserInfo.kt +++ b/login-server/src/main/kotlin/work/fking/pangya/login/auth/UserInfo.kt @@ -3,6 +3,7 @@ package work.fking.pangya.login.auth @JvmRecord data class UserInfo( val uid: Int, + val password: ByteArray, val username: String, val nickname: String? = null, val hasBaseCharacter: Boolean = false diff --git a/login-server/src/main/kotlin/work/fking/pangya/login/net/pipe/LoginHandler.kt b/login-server/src/main/kotlin/work/fking/pangya/login/net/pipe/LoginHandler.kt index 67bf144..9717371 100644 --- a/login-server/src/main/kotlin/work/fking/pangya/login/net/pipe/LoginHandler.kt +++ b/login-server/src/main/kotlin/work/fking/pangya/login/net/pipe/LoginHandler.kt @@ -14,7 +14,7 @@ import work.fking.pangya.login.task.LoginTask import work.fking.pangya.networking.crypt.PangCrypt import work.fking.pangya.networking.crypt.PangCrypt.PangCryptException import work.fking.pangya.networking.protocol.readPString -import work.fking.pangya.networking.protocol.readPStringCharArray +import work.fking.pangya.networking.protocol.readPStringBytes private const val LOGIN_PACKET_ID = 0x1 private const val RECONNECT_PACKET_ID = 0xb @@ -43,7 +43,7 @@ class LoginHandler( private fun handleLogin(ctx: ChannelHandlerContext, buffer: ByteBuf) { val username = buffer.readPString() - val passwordMd5 = buffer.readPStringCharArray() + val passwordMd5 = buffer.readPStringBytes() val channel = ctx.channel() LOGGER.debug("Queueing login request from {} for {}", channel.remoteAddress(), username) loginServer.submitTask(LoginTask(loginServer, channel, cryptKey, username, passwordMd5)) diff --git a/login-server/src/main/kotlin/work/fking/pangya/login/persistence/AccountRepository.kt b/login-server/src/main/kotlin/work/fking/pangya/login/persistence/AccountRepository.kt index 84320ba..9c3a4f9 100644 --- a/login-server/src/main/kotlin/work/fking/pangya/login/persistence/AccountRepository.kt +++ b/login-server/src/main/kotlin/work/fking/pangya/login/persistence/AccountRepository.kt @@ -7,6 +7,7 @@ class AccountRepository(private val dataSource: DataSource) { private val query = """ SELECT a.uid AS uid, + a.password AS password, a.username AS username, a.nickname AS nickname, EXISTS(SELECT 1 FROM player_character pc WHERE pc.account_uid = a.uid) AS hasbasecharacter @@ -14,7 +15,7 @@ class AccountRepository(private val dataSource: DataSource) { WHERE username = ? """.trimIndent() - fun loadUserInfo(username: String, password: ByteArray): UserInfo? { + fun loadUserInfo(username: String): UserInfo? { dataSource.connection.use { conn -> conn.prepareStatement(query).use { stmt -> stmt.setString(1, username) @@ -22,6 +23,7 @@ class AccountRepository(private val dataSource: DataSource) { if (rs.next()) { return UserInfo( uid = rs.getInt("uid"), + password = rs.getBytes("password"), username = rs.getString("username"), nickname = rs.getString("nickname"), hasBaseCharacter = rs.getBoolean("hasbasecharacter") diff --git a/login-server/src/main/kotlin/work/fking/pangya/login/task/LoginTask.kt b/login-server/src/main/kotlin/work/fking/pangya/login/task/LoginTask.kt index ab14bde..f9b69f2 100644 --- a/login-server/src/main/kotlin/work/fking/pangya/login/task/LoginTask.kt +++ b/login-server/src/main/kotlin/work/fking/pangya/login/task/LoginTask.kt @@ -26,7 +26,7 @@ class LoginTask( private val channel: Channel, private val cryptKey: Int, private val username: String, - private val password: CharArray + private val password: ByteArray ) : Runnable { override fun run() { diff --git a/login-server/src/main/resources/psw4j.properties b/login-server/src/main/resources/psw4j.properties new file mode 100644 index 0000000..1a91b06 --- /dev/null +++ b/login-server/src/main/resources/psw4j.properties @@ -0,0 +1,3 @@ +global.banner=false +hash.bcrypt.minor=b +hash.bcrypt.rounds=12 \ No newline at end of file diff --git a/networking/src/main/kotlin/work/fking/pangya/networking/protocol/ByteBufExtensions.kt b/networking/src/main/kotlin/work/fking/pangya/networking/protocol/ByteBufExtensions.kt index cb94fb0..36cf4da 100644 --- a/networking/src/main/kotlin/work/fking/pangya/networking/protocol/ByteBufExtensions.kt +++ b/networking/src/main/kotlin/work/fking/pangya/networking/protocol/ByteBufExtensions.kt @@ -11,13 +11,13 @@ fun ByteBuf.readPString(): String { return String(bytes, StandardCharsets.US_ASCII) } -fun ByteBuf.readPStringCharArray(): CharArray { +fun ByteBuf.readPStringBytes(): ByteArray { val size = readUnsignedShortLE() - val characters = CharArray(size) + val bytes = ByteArray(size) for (i in 0 until size) { - characters[i] = readByte().toInt().toChar() + bytes[i] = readByte() } - return characters + return bytes } fun ByteBuf.readFixedSizeString(size: Int): String { diff --git a/pom.xml b/pom.xml index b3f9d08..82e8b3f 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,7 @@ 21 21 1.9.20 + 1.7.3 9.21.1 3.18.5 5.0.1