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