Rename XteaKey to SymmetricKey

It's now used for both XTEA and ISAAC keys, and there's nothing
XTEA-specific about it so there's no need to duplicate it.

Signed-off-by: Graham <gpe@openrs2.org>
Graham 1 year ago
parent 4ac91e4f29
commit 71b1ac8e20
  1. 6
      archive/src/main/kotlin/org/openrs2/archive/cache/CacheExporter.kt
  2. 20
      archive/src/main/kotlin/org/openrs2/archive/key/BinaryKeyReader.kt
  3. 8
      archive/src/main/kotlin/org/openrs2/archive/key/HdosKeyDownloader.kt
  4. 6
      archive/src/main/kotlin/org/openrs2/archive/key/HexKeyReader.kt
  5. 4
      archive/src/main/kotlin/org/openrs2/archive/key/JsonKeyDownloader.kt
  6. 10
      archive/src/main/kotlin/org/openrs2/archive/key/JsonKeyReader.kt
  7. 10
      archive/src/main/kotlin/org/openrs2/archive/key/KeyBruteForcer.kt
  8. 4
      archive/src/main/kotlin/org/openrs2/archive/key/KeyDownloader.kt
  9. 12
      archive/src/main/kotlin/org/openrs2/archive/key/KeyExporter.kt
  10. 10
      archive/src/main/kotlin/org/openrs2/archive/key/KeyImporter.kt
  11. 4
      archive/src/main/kotlin/org/openrs2/archive/key/KeyReader.kt
  12. 6
      archive/src/main/kotlin/org/openrs2/archive/key/TextKeyReader.kt
  13. 4
      archive/src/main/kotlin/org/openrs2/archive/web/KeysController.kt
  14. 38
      cache/src/main/kotlin/org/openrs2/cache/Archive.kt
  15. 48
      cache/src/main/kotlin/org/openrs2/cache/Cache.kt
  16. 14
      cache/src/main/kotlin/org/openrs2/cache/Js5Compression.kt
  17. 62
      cache/src/test/kotlin/org/openrs2/cache/Js5CompressionTest.kt
  18. 4
      crypto/src/main/kotlin/org/openrs2/crypto/CryptoJacksonModule.kt
  19. 18
      crypto/src/main/kotlin/org/openrs2/crypto/SymmetricKey.kt
  20. 6
      crypto/src/main/kotlin/org/openrs2/crypto/SymmetricKeyDeserializer.kt
  21. 4
      crypto/src/main/kotlin/org/openrs2/crypto/SymmetricKeySerializer.kt
  22. 4
      crypto/src/main/kotlin/org/openrs2/crypto/Xtea.kt
  23. 2
      crypto/src/test/kotlin/org/openrs2/crypto/XteaTest.kt
  24. 6
      protocol/src/main/kotlin/org/openrs2/protocol/login/upstream/CreateAccountCodec.kt
  25. 6
      protocol/src/main/kotlin/org/openrs2/protocol/login/upstream/GameLoginPayload.kt

@ -16,7 +16,7 @@ import org.openrs2.cache.Js5Compression
import org.openrs2.cache.Js5MasterIndex import org.openrs2.cache.Js5MasterIndex
import org.openrs2.cache.MasterIndexFormat import org.openrs2.cache.MasterIndexFormat
import org.openrs2.cache.Store import org.openrs2.cache.Store
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.db.Database import org.openrs2.db.Database
import org.postgresql.util.PGobject import org.postgresql.util.PGobject
import java.sql.Connection import java.sql.Connection
@ -196,7 +196,7 @@ public class CacheExporter @Inject constructor(
val nameHash: Int?, val nameHash: Int?,
val name: String?, val name: String?,
@JsonProperty("mapsquare") val mapSquare: Int?, @JsonProperty("mapsquare") val mapSquare: Int?,
val key: XteaKey val key: SymmetricKey
) )
public suspend fun totalSize(): Long { public suspend fun totalSize(): Long {
@ -779,7 +779,7 @@ public class CacheExporter @Inject constructor(
val k3 = rows.getInt(8) val k3 = rows.getInt(8)
val mapSquare = getMapSquare(name) val mapSquare = getMapSquare(name)
keys += Key(archive, group, nameHash, name, mapSquare, XteaKey(k0, k1, k2, k3)) keys += Key(archive, group, nameHash, name, mapSquare, SymmetricKey(k0, k1, k2, k3))
} }
keys keys

@ -3,17 +3,17 @@ package org.openrs2.archive.key
import io.netty.buffer.ByteBuf import io.netty.buffer.ByteBuf
import io.netty.buffer.Unpooled import io.netty.buffer.Unpooled
import org.openrs2.buffer.use import org.openrs2.buffer.use
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import java.io.InputStream import java.io.InputStream
public object BinaryKeyReader : KeyReader { public object BinaryKeyReader : KeyReader {
override fun read(input: InputStream): Sequence<XteaKey> { override fun read(input: InputStream): Sequence<SymmetricKey> {
Unpooled.wrappedBuffer(input.readBytes()).use { buf -> Unpooled.wrappedBuffer(input.readBytes()).use { buf ->
val len = buf.readableBytes() val len = buf.readableBytes()
if (len == (128 * 128 * 16)) { if (len == (128 * 128 * 16)) {
val keys = read(buf, 0) val keys = read(buf, 0)
require(XteaKey.ZERO in keys) require(SymmetricKey.ZERO in keys)
return keys.asSequence() return keys.asSequence()
} }
@ -22,19 +22,19 @@ public object BinaryKeyReader : KeyReader {
if (maybeShort && !maybeInt) { if (maybeShort && !maybeInt) {
val keys = read(buf, 2) val keys = read(buf, 2)
require(XteaKey.ZERO in keys) require(SymmetricKey.ZERO in keys)
return keys.asSequence() return keys.asSequence()
} else if (!maybeShort && maybeInt) { } else if (!maybeShort && maybeInt) {
val keys = read(buf, 4).asSequence() val keys = read(buf, 4).asSequence()
require(XteaKey.ZERO in keys) require(SymmetricKey.ZERO in keys)
return keys.asSequence() return keys.asSequence()
} else if (maybeShort && maybeInt) { } else if (maybeShort && maybeInt) {
val shortKeys = read(buf, 2) val shortKeys = read(buf, 2)
val intKeys = read(buf, 4) val intKeys = read(buf, 4)
return if (XteaKey.ZERO in shortKeys && XteaKey.ZERO !in intKeys) { return if (SymmetricKey.ZERO in shortKeys && SymmetricKey.ZERO !in intKeys) {
shortKeys.asSequence() shortKeys.asSequence()
} else if (XteaKey.ZERO !in shortKeys && XteaKey.ZERO in intKeys) { } else if (SymmetricKey.ZERO !in shortKeys && SymmetricKey.ZERO in intKeys) {
intKeys.asSequence() intKeys.asSequence()
} else { } else {
throw IllegalArgumentException("Failed to determine if map square IDs are 2 or 4 bytes") throw IllegalArgumentException("Failed to determine if map square IDs are 2 or 4 bytes")
@ -47,8 +47,8 @@ public object BinaryKeyReader : KeyReader {
} }
} }
private fun read(buf: ByteBuf, mapSquareLen: Int): Set<XteaKey> { private fun read(buf: ByteBuf, mapSquareLen: Int): Set<SymmetricKey> {
val keys = mutableSetOf<XteaKey>() val keys = mutableSetOf<SymmetricKey>()
while (buf.isReadable) { while (buf.isReadable) {
buf.skipBytes(mapSquareLen) buf.skipBytes(mapSquareLen)
@ -57,7 +57,7 @@ public object BinaryKeyReader : KeyReader {
val k1 = buf.readInt() val k1 = buf.readInt()
val k2 = buf.readInt() val k2 = buf.readInt()
val k3 = buf.readInt() val k3 = buf.readInt()
keys += XteaKey(k0, k1, k2, k3) keys += SymmetricKey(k0, k1, k2, k3)
} }
return keys return keys

@ -5,7 +5,7 @@ import jakarta.inject.Singleton
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.future.await import kotlinx.coroutines.future.await
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.http.checkStatusCode import org.openrs2.http.checkStatusCode
import java.net.URI import java.net.URI
import java.net.http.HttpClient import java.net.http.HttpClient
@ -21,7 +21,7 @@ public class HdosKeyDownloader @Inject constructor(
return setOf(ENDPOINT) return setOf(ENDPOINT)
} }
override suspend fun download(url: String): Sequence<XteaKey> { override suspend fun download(url: String): Sequence<SymmetricKey> {
val request = HttpRequest.newBuilder(URI(url)) val request = HttpRequest.newBuilder(URI(url))
.GET() .GET()
.timeout(Duration.ofSeconds(30)) .timeout(Duration.ofSeconds(30))
@ -33,7 +33,7 @@ public class HdosKeyDownloader @Inject constructor(
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
response.body().use { input -> response.body().use { input ->
input.bufferedReader().use { reader -> input.bufferedReader().use { reader ->
val keys = mutableSetOf<XteaKey>() val keys = mutableSetOf<SymmetricKey>()
for (line in reader.lineSequence()) { for (line in reader.lineSequence()) {
val parts = line.split(',') val parts = line.split(',')
@ -41,7 +41,7 @@ public class HdosKeyDownloader @Inject constructor(
continue continue
} }
val key = XteaKey.fromHexOrNull(parts[2]) ?: continue val key = SymmetricKey.fromHexOrNull(parts[2]) ?: continue
keys += key keys += key
} }

@ -1,13 +1,13 @@
package org.openrs2.archive.key package org.openrs2.archive.key
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import java.io.InputStream import java.io.InputStream
public object HexKeyReader : KeyReader { public object HexKeyReader : KeyReader {
override fun read(input: InputStream): Sequence<XteaKey> { override fun read(input: InputStream): Sequence<SymmetricKey> {
return input.bufferedReader() return input.bufferedReader()
.lineSequence() .lineSequence()
.map(XteaKey::fromHexOrNull) .map(SymmetricKey::fromHexOrNull)
.filterNotNull() .filterNotNull()
} }
} }

@ -3,7 +3,7 @@ package org.openrs2.archive.key
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.future.await import kotlinx.coroutines.future.await
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.http.checkStatusCode import org.openrs2.http.checkStatusCode
import java.net.URI import java.net.URI
import java.net.http.HttpClient import java.net.http.HttpClient
@ -16,7 +16,7 @@ public abstract class JsonKeyDownloader(
private val client: HttpClient, private val client: HttpClient,
private val jsonKeyReader: JsonKeyReader private val jsonKeyReader: JsonKeyReader
) : KeyDownloader(source) { ) : KeyDownloader(source) {
override suspend fun download(url: String): Sequence<XteaKey> { override suspend fun download(url: String): Sequence<SymmetricKey> {
val request = HttpRequest.newBuilder(URI(url)) val request = HttpRequest.newBuilder(URI(url))
.GET() .GET()
.timeout(Duration.ofSeconds(30)) .timeout(Duration.ofSeconds(30))

@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.treeToValue import com.fasterxml.jackson.module.kotlin.treeToValue
import jakarta.inject.Inject import jakarta.inject.Inject
import jakarta.inject.Singleton import jakarta.inject.Singleton
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.json.Json import org.openrs2.json.Json
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
@ -13,21 +13,21 @@ import java.io.InputStream
public class JsonKeyReader @Inject constructor( public class JsonKeyReader @Inject constructor(
@Json private val mapper: ObjectMapper @Json private val mapper: ObjectMapper
) : KeyReader { ) : KeyReader {
override fun read(input: InputStream): Sequence<XteaKey> { override fun read(input: InputStream): Sequence<SymmetricKey> {
val keys = mutableSetOf<XteaKey>() val keys = mutableSetOf<SymmetricKey>()
val root = mapper.readTree(input) val root = mapper.readTree(input)
when { when {
root.isArray -> { root.isArray -> {
for (entry in root) { for (entry in root) {
val key = entry["key"] ?: entry["keys"] ?: throw IOException("Missing 'key' or 'keys' field") val key = entry["key"] ?: entry["keys"] ?: throw IOException("Missing 'key' or 'keys' field")
keys += mapper.treeToValue<XteaKey?>(key) ?: throw IOException("Key must be non-null") keys += mapper.treeToValue<SymmetricKey?>(key) ?: throw IOException("Key must be non-null")
} }
} }
root.isObject -> { root.isObject -> {
for (entry in root.fields()) { for (entry in root.fields()) {
keys += mapper.treeToValue<XteaKey?>(entry.value) ?: throw IOException("Key must be non-null") keys += mapper.treeToValue<SymmetricKey?>(entry.value) ?: throw IOException("Key must be non-null")
} }
} }

@ -6,7 +6,7 @@ import jakarta.inject.Singleton
import org.openrs2.buffer.crc32 import org.openrs2.buffer.crc32
import org.openrs2.buffer.use import org.openrs2.buffer.use
import org.openrs2.cache.Js5Compression import org.openrs2.cache.Js5Compression
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.db.Database import org.openrs2.db.Database
import java.sql.Connection import java.sql.Connection
import java.sql.Types import java.sql.Types
@ -203,7 +203,7 @@ public class KeyBruteForcer @Inject constructor(
val k1 = rows.getInt(3) val k1 = rows.getInt(3)
val k2 = rows.getInt(4) val k2 = rows.getInt(4)
val k3 = rows.getInt(5) val k3 = rows.getInt(5)
val key = XteaKey(k0, k1, k2, k3) val key = SymmetricKey(k0, k1, k2, k3)
validatedKey = validateKey(data, key, keyId, containerId) validatedKey = validateKey(data, key, keyId, containerId)
if (validatedKey != null) { if (validatedKey != null) {
@ -326,7 +326,7 @@ public class KeyBruteForcer @Inject constructor(
} }
} }
private fun nextKey(connection: Connection, lastKeyId: Long?): Pair<Long, XteaKey>? { private fun nextKey(connection: Connection, lastKeyId: Long?): Pair<Long, SymmetricKey>? {
connection.prepareStatement( connection.prepareStatement(
""" """
SELECT id, (key).k0, (key).k1, (key).k2, (key).k3 SELECT id, (key).k0, (key).k1, (key).k2, (key).k3
@ -350,7 +350,7 @@ public class KeyBruteForcer @Inject constructor(
val k1 = rows.getInt(3) val k1 = rows.getInt(3)
val k2 = rows.getInt(4) val k2 = rows.getInt(4)
val k3 = rows.getInt(5) val k3 = rows.getInt(5)
val key = XteaKey(k0, k1, k2, k3) val key = SymmetricKey(k0, k1, k2, k3)
return Pair(keyId, key) return Pair(keyId, key)
} }
@ -359,7 +359,7 @@ public class KeyBruteForcer @Inject constructor(
private fun validateKey( private fun validateKey(
data: ByteArray, data: ByteArray,
key: XteaKey, key: SymmetricKey,
keyId: Long, keyId: Long,
containerId: Long containerId: Long
): ValidatedKey? { ): ValidatedKey? {

@ -1,10 +1,10 @@
package org.openrs2.archive.key package org.openrs2.archive.key
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
public abstract class KeyDownloader( public abstract class KeyDownloader(
public val source: KeySource public val source: KeySource
) { ) {
public abstract suspend fun getMissingUrls(seenUrls: Set<String>): Set<String> public abstract suspend fun getMissingUrls(seenUrls: Set<String>): Set<String>
public abstract suspend fun download(url: String): Sequence<XteaKey> public abstract suspend fun download(url: String): Sequence<SymmetricKey>
} }

@ -2,7 +2,7 @@ package org.openrs2.archive.key
import jakarta.inject.Inject import jakarta.inject.Inject
import jakarta.inject.Singleton import jakarta.inject.Singleton
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.db.Database import org.openrs2.db.Database
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
import java.io.DataOutputStream import java.io.DataOutputStream
@ -82,11 +82,11 @@ public class KeyExporter @Inject constructor(
} }
} }
public suspend fun exportAll(): List<XteaKey> { public suspend fun exportAll(): List<SymmetricKey> {
return export(validOnly = false) return export(validOnly = false)
} }
public suspend fun exportValid(): List<XteaKey> { public suspend fun exportValid(): List<SymmetricKey> {
return export(validOnly = true) return export(validOnly = true)
} }
@ -116,7 +116,7 @@ public class KeyExporter @Inject constructor(
return analysis return analysis
} }
private suspend fun export(validOnly: Boolean): List<XteaKey> { private suspend fun export(validOnly: Boolean): List<SymmetricKey> {
return database.execute { connection -> return database.execute { connection ->
val query = if (validOnly) { val query = if (validOnly) {
EXPORT_VALID_QUERY EXPORT_VALID_QUERY
@ -126,14 +126,14 @@ public class KeyExporter @Inject constructor(
connection.prepareStatement(query).use { stmt -> connection.prepareStatement(query).use { stmt ->
stmt.executeQuery().use { rows -> stmt.executeQuery().use { rows ->
val keys = mutableListOf<XteaKey>() val keys = mutableListOf<SymmetricKey>()
while (rows.next()) { while (rows.next()) {
val k0 = rows.getInt(1) val k0 = rows.getInt(1)
val k1 = rows.getInt(2) val k1 = rows.getInt(2)
val k2 = rows.getInt(3) val k2 = rows.getInt(3)
val k3 = rows.getInt(4) val k3 = rows.getInt(4)
keys += XteaKey(k0, k1, k2, k3) keys += SymmetricKey(k0, k1, k2, k3)
} }
keys keys

@ -3,7 +3,7 @@ package org.openrs2.archive.key
import com.github.michaelbull.logging.InlineLogger import com.github.michaelbull.logging.InlineLogger
import jakarta.inject.Inject import jakarta.inject.Inject
import jakarta.inject.Singleton import jakarta.inject.Singleton
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.db.Database import org.openrs2.db.Database
import java.io.IOException import java.io.IOException
import java.nio.file.Files import java.nio.file.Files
@ -19,10 +19,10 @@ public class KeyImporter @Inject constructor(
private val jsonKeyReader: JsonKeyReader, private val jsonKeyReader: JsonKeyReader,
private val downloaders: Set<KeyDownloader> private val downloaders: Set<KeyDownloader>
) { ) {
private data class Key(val key: XteaKey, val source: KeySource) private data class Key(val key: SymmetricKey, val source: KeySource)
public suspend fun import(path: Path) { public suspend fun import(path: Path) {
val keys = mutableSetOf<XteaKey>() val keys = mutableSetOf<SymmetricKey>()
for (file in Files.walk(path)) { for (file in Files.walk(path)) {
if (!Files.isRegularFile(file)) { if (!Files.isRegularFile(file)) {
@ -45,7 +45,7 @@ public class KeyImporter @Inject constructor(
} }
} }
keys -= XteaKey.ZERO keys -= SymmetricKey.ZERO
logger.info { "Importing ${keys.size} keys" } logger.info { "Importing ${keys.size} keys" }
@ -108,7 +108,7 @@ public class KeyImporter @Inject constructor(
} }
} }
public suspend fun import(keys: Iterable<XteaKey>, source: KeySource) { public suspend fun import(keys: Iterable<SymmetricKey>, source: KeySource) {
val now = Instant.now() val now = Instant.now()
database.execute { connection -> database.execute { connection ->

@ -1,8 +1,8 @@
package org.openrs2.archive.key package org.openrs2.archive.key
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import java.io.InputStream import java.io.InputStream
public interface KeyReader { public interface KeyReader {
public fun read(input: InputStream): Sequence<XteaKey> public fun read(input: InputStream): Sequence<SymmetricKey>
} }

@ -1,10 +1,10 @@
package org.openrs2.archive.key package org.openrs2.archive.key
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import java.io.InputStream import java.io.InputStream
public object TextKeyReader : KeyReader { public object TextKeyReader : KeyReader {
override fun read(input: InputStream): Sequence<XteaKey> { override fun read(input: InputStream): Sequence<SymmetricKey> {
val reader = input.bufferedReader() val reader = input.bufferedReader()
val k0 = reader.readLine()?.toIntOrNull() ?: return emptySequence() val k0 = reader.readLine()?.toIntOrNull() ?: return emptySequence()
@ -12,6 +12,6 @@ public object TextKeyReader : KeyReader {
val k2 = reader.readLine()?.toIntOrNull() ?: return emptySequence() val k2 = reader.readLine()?.toIntOrNull() ?: return emptySequence()
val k3 = reader.readLine()?.toIntOrNull() ?: return emptySequence() val k3 = reader.readLine()?.toIntOrNull() ?: return emptySequence()
return sequenceOf(XteaKey(k0, k1, k2, k3)) return sequenceOf(SymmetricKey(k0, k1, k2, k3))
} }
} }

@ -10,7 +10,7 @@ import jakarta.inject.Singleton
import org.openrs2.archive.key.KeyExporter import org.openrs2.archive.key.KeyExporter
import org.openrs2.archive.key.KeyImporter import org.openrs2.archive.key.KeyImporter
import org.openrs2.archive.key.KeySource import org.openrs2.archive.key.KeySource
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
@Singleton @Singleton
public class KeysController @Inject constructor( public class KeysController @Inject constructor(
@ -24,7 +24,7 @@ public class KeysController @Inject constructor(
} }
public suspend fun import(call: ApplicationCall) { public suspend fun import(call: ApplicationCall) {
val keys = call.receive<Array<IntArray>>().mapTo(mutableSetOf(), XteaKey::fromIntArray) val keys = call.receive<Array<IntArray>>().mapTo(mutableSetOf(), SymmetricKey::fromIntArray)
if (keys.isNotEmpty()) { if (keys.isNotEmpty()) {
importer.import(keys, KeySource.API) importer.import(keys, KeySource.API)

@ -7,7 +7,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMap
import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMaps import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMaps
import org.openrs2.buffer.crc32 import org.openrs2.buffer.crc32
import org.openrs2.buffer.use import org.openrs2.buffer.use
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.crypto.whirlpool import org.openrs2.crypto.whirlpool
import org.openrs2.util.krHashCode import org.openrs2.util.krHashCode
import java.io.FileNotFoundException import java.io.FileNotFoundException
@ -23,7 +23,7 @@ public abstract class Archive internal constructor(
internal inner class Unpacked( internal inner class Unpacked(
private val entry: Js5Index.MutableGroup, private val entry: Js5Index.MutableGroup,
val key: XteaKey, val key: SymmetricKey,
private var files: Int2ObjectSortedMap<ByteBuf> private var files: Int2ObjectSortedMap<ByteBuf>
) { ) {
private var dirty = false private var dirty = false
@ -193,7 +193,7 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun read(group: Int, file: Int, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun read(group: Int, file: Int, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
require(group >= 0 && file >= 0) require(group >= 0 && file >= 0)
val entry = index[group] ?: throw FileNotFoundException() val entry = index[group] ?: throw FileNotFoundException()
@ -202,19 +202,19 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun readNamed(groupNameHash: Int, fileNameHash: Int, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun readNamed(groupNameHash: Int, fileNameHash: Int, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
val entry = index.getNamed(groupNameHash) ?: throw FileNotFoundException() val entry = index.getNamed(groupNameHash) ?: throw FileNotFoundException()
val unpacked = getUnpacked(entry, key) val unpacked = getUnpacked(entry, key)
return unpacked.readNamed(fileNameHash) return unpacked.readNamed(fileNameHash)
} }
@JvmOverloads @JvmOverloads
public fun read(group: String, file: String, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun read(group: String, file: String, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
return readNamed(group.krHashCode(), file.krHashCode(), key) return readNamed(group.krHashCode(), file.krHashCode(), key)
} }
@JvmOverloads @JvmOverloads
public fun readNamedGroup(groupNameHash: Int, file: Int, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun readNamedGroup(groupNameHash: Int, file: Int, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
require(file >= 0) require(file >= 0)
val entry = index.getNamed(groupNameHash) ?: throw FileNotFoundException() val entry = index.getNamed(groupNameHash) ?: throw FileNotFoundException()
@ -223,12 +223,12 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun read(group: String, file: Int, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun read(group: String, file: Int, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
return readNamedGroup(group.krHashCode(), file, key) return readNamedGroup(group.krHashCode(), file, key)
} }
@JvmOverloads @JvmOverloads
public fun write(group: Int, file: Int, buf: ByteBuf, key: XteaKey = XteaKey.ZERO) { public fun write(group: Int, file: Int, buf: ByteBuf, key: SymmetricKey = SymmetricKey.ZERO) {
require(group >= 0 && file >= 0) require(group >= 0 && file >= 0)
val entry = index.createOrGet(group) val entry = index.createOrGet(group)
@ -239,7 +239,7 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun writeNamed(groupNameHash: Int, fileNameHash: Int, buf: ByteBuf, key: XteaKey = XteaKey.ZERO) { public fun writeNamed(groupNameHash: Int, fileNameHash: Int, buf: ByteBuf, key: SymmetricKey = SymmetricKey.ZERO) {
val entry = index.createOrGetNamed(groupNameHash) val entry = index.createOrGetNamed(groupNameHash)
val unpacked = createOrGetUnpacked(entry, key, isOverwritingNamed(entry, fileNameHash)) val unpacked = createOrGetUnpacked(entry, key, isOverwritingNamed(entry, fileNameHash))
unpacked.writeNamed(fileNameHash, buf) unpacked.writeNamed(fileNameHash, buf)
@ -249,12 +249,12 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun write(group: String, file: String, buf: ByteBuf, key: XteaKey = XteaKey.ZERO) { public fun write(group: String, file: String, buf: ByteBuf, key: SymmetricKey = SymmetricKey.ZERO) {
return writeNamed(group.krHashCode(), file.krHashCode(), buf, key) return writeNamed(group.krHashCode(), file.krHashCode(), buf, key)
} }
@JvmOverloads @JvmOverloads
public fun writeNamedGroup(groupNameHash: Int, file: Int, buf: ByteBuf, key: XteaKey = XteaKey.ZERO) { public fun writeNamedGroup(groupNameHash: Int, file: Int, buf: ByteBuf, key: SymmetricKey = SymmetricKey.ZERO) {
require(file >= 0) require(file >= 0)
val entry = index.createOrGetNamed(groupNameHash) val entry = index.createOrGetNamed(groupNameHash)
@ -266,7 +266,7 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun write(group: String, file: Int, buf: ByteBuf, key: XteaKey = XteaKey.ZERO) { public fun write(group: String, file: Int, buf: ByteBuf, key: SymmetricKey = SymmetricKey.ZERO) {
return writeNamedGroup(group.krHashCode(), file, buf, key) return writeNamedGroup(group.krHashCode(), file, buf, key)
} }
@ -293,7 +293,7 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun remove(group: Int, file: Int, key: XteaKey = XteaKey.ZERO) { public fun remove(group: Int, file: Int, key: SymmetricKey = SymmetricKey.ZERO) {
require(group >= 0 && file >= 0) require(group >= 0 && file >= 0)
val entry = index[group] ?: return val entry = index[group] ?: return
@ -310,7 +310,7 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun removeNamed(groupNameHash: Int, fileNameHash: Int, key: XteaKey = XteaKey.ZERO) { public fun removeNamed(groupNameHash: Int, fileNameHash: Int, key: SymmetricKey = SymmetricKey.ZERO) {
val entry = index.getNamed(groupNameHash) ?: return val entry = index.getNamed(groupNameHash) ?: return
if (isOverwritingNamed(entry, fileNameHash)) { if (isOverwritingNamed(entry, fileNameHash)) {
@ -325,12 +325,12 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun remove(group: String, file: String, key: XteaKey = XteaKey.ZERO) { public fun remove(group: String, file: String, key: SymmetricKey = SymmetricKey.ZERO) {
return removeNamed(group.krHashCode(), file.krHashCode(), key) return removeNamed(group.krHashCode(), file.krHashCode(), key)
} }
@JvmOverloads @JvmOverloads
public fun removeNamedGroup(groupNameHash: Int, file: Int, key: XteaKey = XteaKey.ZERO) { public fun removeNamedGroup(groupNameHash: Int, file: Int, key: SymmetricKey = SymmetricKey.ZERO) {
require(file >= 0) require(file >= 0)
val entry = index.getNamed(groupNameHash) ?: return val entry = index.getNamed(groupNameHash) ?: return
@ -347,7 +347,7 @@ public abstract class Archive internal constructor(
} }
@JvmOverloads @JvmOverloads
public fun remove(group: String, file: Int, key: XteaKey = XteaKey.ZERO) { public fun remove(group: String, file: Int, key: SymmetricKey = SymmetricKey.ZERO) {
removeNamedGroup(group.krHashCode(), file, key) removeNamedGroup(group.krHashCode(), file, key)
} }
@ -388,7 +388,7 @@ public abstract class Archive internal constructor(
return fileEntry.nameHash == fileNameHash return fileEntry.nameHash == fileNameHash
} }
private fun createOrGetUnpacked(entry: Js5Index.MutableGroup, key: XteaKey, overwrite: Boolean): Unpacked { private fun createOrGetUnpacked(entry: Js5Index.MutableGroup, key: SymmetricKey, overwrite: Boolean): Unpacked {
return if (entry.size == 0 || overwrite) { return if (entry.size == 0 || overwrite) {
val unpacked = Unpacked(entry, key, Int2ObjectAVLTreeMap()) val unpacked = Unpacked(entry, key, Int2ObjectAVLTreeMap())
unpackedCache.put(archive, entry.id, unpacked) unpackedCache.put(archive, entry.id, unpacked)
@ -398,7 +398,7 @@ public abstract class Archive internal constructor(
} }
} }
private fun getUnpacked(entry: Js5Index.MutableGroup, key: XteaKey): Unpacked { private fun getUnpacked(entry: Js5Index.MutableGroup, key: SymmetricKey): Unpacked {
var unpacked = unpackedCache.get(archive, entry.id) var unpacked = unpackedCache.get(archive, entry.id)
if (unpacked != null) { if (unpacked != null) {
/* /*

@ -3,7 +3,7 @@ package org.openrs2.cache
import io.netty.buffer.ByteBuf import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufAllocator import io.netty.buffer.ByteBufAllocator
import org.openrs2.buffer.use import org.openrs2.buffer.use
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.util.krHashCode import org.openrs2.util.krHashCode
import java.io.Closeable import java.io.Closeable
import java.io.FileNotFoundException import java.io.FileNotFoundException
@ -142,35 +142,45 @@ public class Cache private constructor(
} }
@JvmOverloads @JvmOverloads
public fun read(archive: Int, group: Int, file: Int, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun read(archive: Int, group: Int, file: Int, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
checkArchive(archive) checkArchive(archive)
return archives[archive]?.read(group, file, key) ?: throw FileNotFoundException() return archives[archive]?.read(group, file, key) ?: throw FileNotFoundException()
} }
@JvmOverloads @JvmOverloads
public fun readNamed(archive: Int, groupNameHash: Int, fileNameHash: Int, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun readNamed(
archive: Int,
groupNameHash: Int,
fileNameHash: Int,
key: SymmetricKey = SymmetricKey.ZERO
): ByteBuf {
checkArchive(archive) checkArchive(archive)
return archives[archive]?.readNamed(groupNameHash, fileNameHash, key) ?: throw FileNotFoundException() return archives[archive]?.readNamed(groupNameHash, fileNameHash, key) ?: throw FileNotFoundException()
} }
@JvmOverloads @JvmOverloads
public fun read(archive: Int, group: String, file: String, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun read(archive: Int, group: String, file: String, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
return readNamed(archive, group.krHashCode(), file.krHashCode(), key) return readNamed(archive, group.krHashCode(), file.krHashCode(), key)
} }
@JvmOverloads @JvmOverloads
public fun readNamedGroup(archive: Int, groupNameHash: Int, file: Int, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun readNamedGroup(
archive: Int,
groupNameHash: Int,
file: Int,
key: SymmetricKey = SymmetricKey.ZERO
): ByteBuf {
checkArchive(archive) checkArchive(archive)
return archives[archive]?.readNamedGroup(groupNameHash, file, key) ?: throw FileNotFoundException() return archives[archive]?.readNamedGroup(groupNameHash, file, key) ?: throw FileNotFoundException()
} }
@JvmOverloads @JvmOverloads
public fun read(archive: Int, group: String, file: Int, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun read(archive: Int, group: String, file: Int, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
return readNamedGroup(archive, group.krHashCode(), file, key) return readNamedGroup(archive, group.krHashCode(), file, key)
} }
@JvmOverloads @JvmOverloads
public fun write(archive: Int, group: Int, file: Int, buf: ByteBuf, key: XteaKey = XteaKey.ZERO) { public fun write(archive: Int, group: Int, file: Int, buf: ByteBuf, key: SymmetricKey = SymmetricKey.ZERO) {
checkArchive(archive) checkArchive(archive)
createOrGetArchive(archive).write(group, file, buf, key) createOrGetArchive(archive).write(group, file, buf, key)
} }
@ -181,25 +191,31 @@ public class Cache private constructor(
groupNameHash: Int, groupNameHash: Int,
fileNameHash: Int, fileNameHash: Int,
buf: ByteBuf, buf: ByteBuf,
key: XteaKey = XteaKey.ZERO key: SymmetricKey = SymmetricKey.ZERO
) { ) {
checkArchive(archive) checkArchive(archive)
createOrGetArchive(archive).writeNamed(groupNameHash, fileNameHash, buf, key) createOrGetArchive(archive).writeNamed(groupNameHash, fileNameHash, buf, key)
} }
@JvmOverloads @JvmOverloads
public fun write(archive: Int, group: String, file: String, buf: ByteBuf, key: XteaKey = XteaKey.ZERO) { public fun write(archive: Int, group: String, file: String, buf: ByteBuf, key: SymmetricKey = SymmetricKey.ZERO) {
writeNamed(archive, group.krHashCode(), file.krHashCode(), buf, key) writeNamed(archive, group.krHashCode(), file.krHashCode(), buf, key)
} }
@JvmOverloads @JvmOverloads
public fun writeNamedGroup(archive: Int, groupNameHash: Int, file: Int, buf: ByteBuf, key: XteaKey = XteaKey.ZERO) { public fun writeNamedGroup(
archive: Int,
groupNameHash: Int,
file: Int,
buf: ByteBuf,
key: SymmetricKey = SymmetricKey.ZERO
) {
checkArchive(archive) checkArchive(archive)
createOrGetArchive(archive).writeNamedGroup(groupNameHash, file, buf, key) createOrGetArchive(archive).writeNamedGroup(groupNameHash, file, buf, key)
} }
@JvmOverloads @JvmOverloads
public fun write(archive: Int, group: String, file: Int, buf: ByteBuf, key: XteaKey = XteaKey.ZERO) { public fun write(archive: Int, group: String, file: Int, buf: ByteBuf, key: SymmetricKey = SymmetricKey.ZERO) {
writeNamedGroup(archive, group.krHashCode(), file, buf, key) writeNamedGroup(archive, group.krHashCode(), file, buf, key)
} }
@ -233,30 +249,30 @@ public class Cache private constructor(
} }
@JvmOverloads @JvmOverloads
public fun remove(archive: Int, group: Int, file: Int, key: XteaKey = XteaKey.ZERO) { public fun remove(archive: Int, group: Int, file: Int, key: SymmetricKey = SymmetricKey.ZERO) {
checkArchive(archive) checkArchive(archive)
archives[archive]?.remove(group, file, key) archives[archive]?.remove(group, file, key)
} }
@JvmOverloads @JvmOverloads
public fun removeNamed(archive: Int, groupNameHash: Int, fileNameHash: Int, key: XteaKey = XteaKey.ZERO) { public fun removeNamed(archive: Int, groupNameHash: Int, fileNameHash: Int, key: SymmetricKey = SymmetricKey.ZERO) {
checkArchive(archive) checkArchive(archive)
archives[archive]?.removeNamed(groupNameHash, fileNameHash, key) archives[archive]?.removeNamed(groupNameHash, fileNameHash, key)
} }
@JvmOverloads @JvmOverloads
public fun remove(archive: Int, group: String, file: String, key: XteaKey = XteaKey.ZERO) { public fun remove(archive: Int, group: String, file: String, key: SymmetricKey = SymmetricKey.ZERO) {
return removeNamed(archive, group.krHashCode(), file.krHashCode(), key) return removeNamed(archive, group.krHashCode(), file.krHashCode(), key)
} }
@JvmOverloads @JvmOverloads
public fun removeNamedGroup(archive: Int, groupNameHash: Int, file: Int, key: XteaKey = XteaKey.ZERO) { public fun removeNamedGroup(archive: Int, groupNameHash: Int, file: Int, key: SymmetricKey = SymmetricKey.ZERO) {
checkArchive(archive) checkArchive(archive)
archives[archive]?.removeNamedGroup(groupNameHash, file, key) archives[archive]?.removeNamedGroup(groupNameHash, file, key)
} }
@JvmOverloads @JvmOverloads
public fun remove(archive: Int, group: String, file: Int, key: XteaKey = XteaKey.ZERO) { public fun remove(archive: Int, group: String, file: Int, key: SymmetricKey = SymmetricKey.ZERO) {
removeNamedGroup(archive, group.krHashCode(), file, key) removeNamedGroup(archive, group.krHashCode(), file, key)
} }

@ -4,7 +4,7 @@ import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufInputStream import io.netty.buffer.ByteBufInputStream
import io.netty.buffer.ByteBufOutputStream import io.netty.buffer.ByteBufOutputStream
import org.openrs2.buffer.use import org.openrs2.buffer.use
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.crypto.xteaDecrypt import org.openrs2.crypto.xteaDecrypt
import org.openrs2.crypto.xteaEncrypt import org.openrs2.crypto.xteaEncrypt
import java.io.IOException import java.io.IOException
@ -19,7 +19,7 @@ public object Js5Compression {
private const val LZMA_PRESET_DICT_SIZE_MAX = 1 shl 26 private const val LZMA_PRESET_DICT_SIZE_MAX = 1 shl 26
@JvmOverloads @JvmOverloads
public fun compress(input: ByteBuf, type: Js5CompressionType, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun compress(input: ByteBuf, type: Js5CompressionType, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
input.alloc().buffer().use { output -> input.alloc().buffer().use { output ->
output.writeByte(type.ordinal) output.writeByte(type.ordinal)
@ -62,7 +62,7 @@ public object Js5Compression {
input: ByteBuf, input: ByteBuf,
enableLzma: Boolean = false, enableLzma: Boolean = false,
enableUncompressedEncryption: Boolean = false, enableUncompressedEncryption: Boolean = false,
key: XteaKey = XteaKey.ZERO key: SymmetricKey = SymmetricKey.ZERO
): ByteBuf { ): ByteBuf {
val types = mutableListOf(Js5CompressionType.BZIP2, Js5CompressionType.GZIP) val types = mutableListOf(Js5CompressionType.BZIP2, Js5CompressionType.GZIP)
if (enableLzma) { if (enableLzma) {
@ -109,7 +109,7 @@ public object Js5Compression {
} }
@JvmOverloads @JvmOverloads
public fun uncompress(input: ByteBuf, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun uncompress(input: ByteBuf, key: SymmetricKey = SymmetricKey.ZERO): ByteBuf {
if (input.readableBytes() < 5) { if (input.readableBytes() < 5) {
throw IOException("Missing header") throw IOException("Missing header")
} }
@ -169,10 +169,10 @@ public object Js5Compression {
} }
public fun uncompressUnlessEncrypted(input: ByteBuf): ByteBuf? { public fun uncompressUnlessEncrypted(input: ByteBuf): ByteBuf? {
return uncompressIfKeyValid(input, XteaKey.ZERO) return uncompressIfKeyValid(input, SymmetricKey.ZERO)
} }
public fun uncompressIfKeyValid(input: ByteBuf, key: XteaKey): ByteBuf? { public fun uncompressIfKeyValid(input: ByteBuf, key: SymmetricKey): ByteBuf? {
if (input.readableBytes() < 5) { if (input.readableBytes() < 5) {
throw IOException("Missing header") throw IOException("Missing header")
} }
@ -360,7 +360,7 @@ public object Js5Compression {
} }
} }
private fun decrypt(buf: ByteBuf, len: Int, key: XteaKey): ByteBuf { private fun decrypt(buf: ByteBuf, len: Int, key: SymmetricKey): ByteBuf {
if (key.isZero) { if (key.isZero) {
return buf.readRetainedSlice(len) return buf.readRetainedSlice(len)
} }

@ -4,7 +4,7 @@ import io.netty.buffer.ByteBuf
import io.netty.buffer.Unpooled import io.netty.buffer.Unpooled
import org.openrs2.buffer.copiedBuffer import org.openrs2.buffer.copiedBuffer
import org.openrs2.buffer.use import org.openrs2.buffer.use
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import java.io.IOException import java.io.IOException
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -276,7 +276,7 @@ class Js5CompressionTest {
} }
assertFailsWith<IOException> { assertFailsWith<IOException> {
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO)?.release() Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO)?.release()
} }
} }
} }
@ -289,7 +289,7 @@ class Js5CompressionTest {
} }
assertFailsWith<IOException> { assertFailsWith<IOException> {
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO)?.release() Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO)?.release()
} }
} }
} }
@ -301,7 +301,7 @@ class Js5CompressionTest {
Js5Compression.uncompress(compressed.slice()).release() Js5Compression.uncompress(compressed.slice()).release()
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { uncompressed -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { uncompressed ->
assertNull(uncompressed) assertNull(uncompressed)
} }
} }
@ -315,7 +315,7 @@ class Js5CompressionTest {
} }
assertFailsWith<IOException> { assertFailsWith<IOException> {
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO)?.release() Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO)?.release()
} }
} }
} }
@ -327,7 +327,7 @@ class Js5CompressionTest {
Js5Compression.uncompress(compressed.slice()).release() Js5Compression.uncompress(compressed.slice()).release()
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { uncompressed -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { uncompressed ->
assertNull(uncompressed) assertNull(uncompressed)
} }
} }
@ -340,7 +340,7 @@ class Js5CompressionTest {
Js5Compression.uncompress(compressed.slice()).release() Js5Compression.uncompress(compressed.slice()).release()
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { uncompressed -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { uncompressed ->
assertNull(uncompressed) assertNull(uncompressed)
} }
} }
@ -353,7 +353,7 @@ class Js5CompressionTest {
Js5Compression.uncompress(compressed.slice()).release() Js5Compression.uncompress(compressed.slice()).release()
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { uncompressed -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { uncompressed ->
assertNull(uncompressed) assertNull(uncompressed)
} }
} }
@ -366,7 +366,7 @@ class Js5CompressionTest {
Js5Compression.uncompress(compressed.slice()).release() Js5Compression.uncompress(compressed.slice()).release()
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { uncompressed -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { uncompressed ->
assertNull(uncompressed) assertNull(uncompressed)
} }
} }
@ -379,7 +379,7 @@ class Js5CompressionTest {
Js5Compression.uncompress(compressed.slice()).release() Js5Compression.uncompress(compressed.slice()).release()
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { uncompressed -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { uncompressed ->
assertNull(uncompressed) assertNull(uncompressed)
} }
} }
@ -392,7 +392,7 @@ class Js5CompressionTest {
Js5Compression.uncompress(compressed.slice()).release() Js5Compression.uncompress(compressed.slice()).release()
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { uncompressed -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { uncompressed ->
assertNull(uncompressed) assertNull(uncompressed)
} }
} }
@ -406,7 +406,7 @@ class Js5CompressionTest {
assertEquals(expected, actual) assertEquals(expected, actual)
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { actual ->
assertEquals(expected, actual) assertEquals(expected, actual)
} }
@ -429,7 +429,7 @@ class Js5CompressionTest {
assertEquals(expected, actual) assertEquals(expected, actual)
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { actual ->
assertEquals(expected, actual) assertEquals(expected, actual)
} }
@ -447,7 +447,7 @@ class Js5CompressionTest {
assertNull(actual) assertNull(actual)
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
@ -462,7 +462,7 @@ class Js5CompressionTest {
} }
read("bzip2-invalid-magic.dat").use { compressed -> read("bzip2-invalid-magic.dat").use { compressed ->
Js5Compression.uncompressIfKeyValid(compressed, XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed, SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
} }
@ -476,7 +476,7 @@ class Js5CompressionTest {
assertEquals(expected, actual) assertEquals(expected, actual)
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { actual ->
assertEquals(expected, actual) assertEquals(expected, actual)
} }
@ -494,7 +494,7 @@ class Js5CompressionTest {
assertNull(actual) assertNull(actual)
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
@ -509,13 +509,13 @@ class Js5CompressionTest {
} }
read("gzip-invalid-magic.dat").use { compressed -> read("gzip-invalid-magic.dat").use { compressed ->
Js5Compression.uncompressIfKeyValid(compressed, XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed, SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
} }
read("gzip-invalid-method.dat").use { compressed -> read("gzip-invalid-method.dat").use { compressed ->
Js5Compression.uncompressIfKeyValid(compressed, XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed, SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
} }
@ -529,7 +529,7 @@ class Js5CompressionTest {
assertEquals(expected, actual) assertEquals(expected, actual)
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { actual ->
assertEquals(expected, actual) assertEquals(expected, actual)
} }
@ -547,7 +547,7 @@ class Js5CompressionTest {
assertNull(actual) assertNull(actual)
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
@ -562,19 +562,19 @@ class Js5CompressionTest {
} }
read("lzma-dict-size-negative.dat").use { compressed -> read("lzma-dict-size-negative.dat").use { compressed ->
Js5Compression.uncompressIfKeyValid(compressed, XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed, SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
} }
read("lzma-dict-size-larger-than-preset.dat").use { compressed -> read("lzma-dict-size-larger-than-preset.dat").use { compressed ->
Js5Compression.uncompressIfKeyValid(compressed, XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed, SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
} }
read("lzma-invalid-pb.dat").use { compressed -> read("lzma-invalid-pb.dat").use { compressed ->
Js5Compression.uncompressIfKeyValid(compressed, XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed, SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
} }
@ -584,7 +584,7 @@ class Js5CompressionTest {
fun testKeyValidShorterThanTwoBlocks() { fun testKeyValidShorterThanTwoBlocks() {
read("shorter-than-two-blocks.dat").use { compressed -> read("shorter-than-two-blocks.dat").use { compressed ->
assertFailsWith<IOException> { assertFailsWith<IOException> {
Js5Compression.uncompressIfKeyValid(compressed, XteaKey.ZERO)?.release() Js5Compression.uncompressIfKeyValid(compressed, SymmetricKey.ZERO)?.release()
} }
} }
} }
@ -597,7 +597,7 @@ class Js5CompressionTest {
} }
assertFailsWith<IOException> { assertFailsWith<IOException> {
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO)?.release() Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO)?.release()
} }
} }
} }
@ -609,7 +609,7 @@ class Js5CompressionTest {
Js5Compression.uncompress(compressed.slice()).release() Js5Compression.uncompress(compressed.slice()).release()
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
} }
@ -622,7 +622,7 @@ class Js5CompressionTest {
Js5Compression.uncompress(compressed.slice()).release() Js5Compression.uncompress(compressed.slice()).release()
} }
Js5Compression.uncompressIfKeyValid(compressed.slice(), XteaKey.ZERO).use { actual -> Js5Compression.uncompressIfKeyValid(compressed.slice(), SymmetricKey.ZERO).use { actual ->
assertNull(actual) assertNull(actual)
} }
} }
@ -719,7 +719,7 @@ class Js5CompressionTest {
read("missing-header.dat").use { compressed -> read("missing-header.dat").use { compressed ->
assertFailsWith<IOException> { assertFailsWith<IOException> {
Js5Compression.uncompressIfKeyValid(compressed, XteaKey.ZERO) Js5Compression.uncompressIfKeyValid(compressed, SymmetricKey.ZERO)
} }
} }
@ -737,7 +737,7 @@ class Js5CompressionTest {
} }
private companion object { private companion object {
private val KEY = XteaKey.fromHex("00112233445566778899AABBCCDDEEFF") private val KEY = SymmetricKey.fromHex("00112233445566778899AABBCCDDEEFF")
private val INVALID_KEY = XteaKey.fromHex("0123456789ABCDEF0123456789ABCDEF") private val INVALID_KEY = SymmetricKey.fromHex("0123456789ABCDEF0123456789ABCDEF")
} }
} }

@ -6,7 +6,7 @@ import jakarta.inject.Singleton
@Singleton @Singleton
public class CryptoJacksonModule : SimpleModule() { public class CryptoJacksonModule : SimpleModule() {
init { init {
addDeserializer(XteaKey::class.java, XteaKeyDeserializer) addDeserializer(SymmetricKey::class.java, SymmetricKeyDeserializer)
addSerializer(XteaKey::class.java, XteaKeySerializer) addSerializer(SymmetricKey::class.java, SymmetricKeySerializer)
} }
} }

@ -2,7 +2,7 @@ package org.openrs2.crypto
import java.security.SecureRandom import java.security.SecureRandom
public data class XteaKey( public data class SymmetricKey(
public val k0: Int, public val k0: Int,
public val k1: Int, public val k1: Int,
public val k2: Int, public val k2: Int,
@ -28,28 +28,28 @@ public data class XteaKey(
public companion object { public companion object {
@JvmStatic @JvmStatic
public val ZERO: XteaKey = XteaKey(0, 0, 0, 0) public val ZERO: SymmetricKey = SymmetricKey(0, 0, 0, 0)
@JvmStatic @JvmStatic
@JvmOverloads @JvmOverloads
public fun generate(r: SecureRandom = secureRandom): XteaKey { public fun generate(r: SecureRandom = secureRandom): SymmetricKey {
return XteaKey(r.nextInt(), r.nextInt(), r.nextInt(), r.nextInt()) return SymmetricKey(r.nextInt(), r.nextInt(), r.nextInt(), r.nextInt())
} }
@JvmStatic @JvmStatic
public fun fromIntArray(a: IntArray): XteaKey { public fun fromIntArray(a: IntArray): SymmetricKey {
require(a.size == 4) require(a.size == 4)
return XteaKey(a[0], a[1], a[2], a[3]) return SymmetricKey(a[0], a[1], a[2], a[3])
} }
@JvmStatic @JvmStatic
public fun fromHex(s: String): XteaKey { public fun fromHex(s: String): SymmetricKey {
return fromHexOrNull(s) ?: throw IllegalArgumentException() return fromHexOrNull(s) ?: throw IllegalArgumentException()
} }
@JvmStatic @JvmStatic
public fun fromHexOrNull(s: String): XteaKey? { public fun fromHexOrNull(s: String): SymmetricKey? {
if (s.length != 32) { if (s.length != 32) {
return null return null
} }
@ -60,7 +60,7 @@ public data class XteaKey(
val k2 = Integer.parseUnsignedInt(s, 16, 24, 16) val k2 = Integer.parseUnsignedInt(s, 16, 24, 16)
val k3 = Integer.parseUnsignedInt(s, 24, 32, 16) val k3 = Integer.parseUnsignedInt(s, 24, 32, 16)
XteaKey(k0, k1, k2, k3) SymmetricKey(k0, k1, k2, k3)
} catch (ex: NumberFormatException) { } catch (ex: NumberFormatException) {
null null
} }

@ -4,8 +4,8 @@ import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.deser.std.StdDeserializer import com.fasterxml.jackson.databind.deser.std.StdDeserializer
public object XteaKeyDeserializer : StdDeserializer<XteaKey>(XteaKey::class.java) { public object SymmetricKeyDeserializer : StdDeserializer<SymmetricKey>(SymmetricKey::class.java) {
override fun deserialize(parser: JsonParser, ctx: DeserializationContext): XteaKey { override fun deserialize(parser: JsonParser, ctx: DeserializationContext): SymmetricKey {
return XteaKey.fromIntArray(ctx.readValue(parser, IntArray::class.java)) return SymmetricKey.fromIntArray(ctx.readValue(parser, IntArray::class.java))
} }
} }

@ -4,8 +4,8 @@ import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.SerializerProvider import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.ser.std.StdSerializer import com.fasterxml.jackson.databind.ser.std.StdSerializer
public object XteaKeySerializer : StdSerializer<XteaKey>(XteaKey::class.java) { public object SymmetricKeySerializer : StdSerializer<SymmetricKey>(SymmetricKey::class.java) {
override fun serialize(value: XteaKey, gen: JsonGenerator, provider: SerializerProvider) { override fun serialize(value: SymmetricKey, gen: JsonGenerator, provider: SerializerProvider) {
gen.writeStartArray() gen.writeStartArray()
gen.writeNumber(value.k0) gen.writeNumber(value.k0)
gen.writeNumber(value.k1) gen.writeNumber(value.k1)

@ -7,7 +7,7 @@ private const val ROUNDS = 32
public const val XTEA_BLOCK_SIZE: Int = 8 public const val XTEA_BLOCK_SIZE: Int = 8
private const val BLOCK_SIZE_MASK = XTEA_BLOCK_SIZE - 1 private const val BLOCK_SIZE_MASK = XTEA_BLOCK_SIZE - 1
public fun ByteBuf.xteaEncrypt(index: Int, length: Int, key: XteaKey) { public fun ByteBuf.xteaEncrypt(index: Int, length: Int, key: SymmetricKey) {
val k = key.toIntArray() val k = key.toIntArray()
val end = index + (length and BLOCK_SIZE_MASK.inv()) val end = index + (length and BLOCK_SIZE_MASK.inv())
@ -27,7 +27,7 @@ public fun ByteBuf.xteaEncrypt(index: Int, length: Int, key: XteaKey) {
} }
} }
public fun ByteBuf.xteaDecrypt(index: Int, length: Int, key: XteaKey) { public fun ByteBuf.xteaDecrypt(index: Int, length: Int, key: SymmetricKey) {
val k = key.toIntArray() val k = key.toIntArray()
val end = index + (length and BLOCK_SIZE_MASK.inv()) val end = index + (length and BLOCK_SIZE_MASK.inv())

@ -8,7 +8,7 @@ import kotlin.test.assertEquals
class XteaTest { class XteaTest {
private class TestVector(key: String, plaintext: String, ciphertext: String) { private class TestVector(key: String, plaintext: String, ciphertext: String) {
val key = XteaKey.fromHex(key) val key = SymmetricKey.fromHex(key)
val plaintext: ByteArray = ByteBufUtil.decodeHexDump(plaintext) val plaintext: ByteArray = ByteBufUtil.decodeHexDump(plaintext)
val ciphertext: ByteArray = ByteBufUtil.decodeHexDump(ciphertext) val ciphertext: ByteArray = ByteBufUtil.decodeHexDump(ciphertext)
} }

@ -9,8 +9,8 @@ import org.openrs2.buffer.use
import org.openrs2.buffer.writeString import org.openrs2.buffer.writeString
import org.openrs2.crypto.Rsa import org.openrs2.crypto.Rsa
import org.openrs2.crypto.StreamCipher import org.openrs2.crypto.StreamCipher
import org.openrs2.crypto.SymmetricKey
import org.openrs2.crypto.XTEA_BLOCK_SIZE import org.openrs2.crypto.XTEA_BLOCK_SIZE
import org.openrs2.crypto.XteaKey
import org.openrs2.crypto.publicKey import org.openrs2.crypto.publicKey
import org.openrs2.crypto.rsa import org.openrs2.crypto.rsa
import org.openrs2.crypto.secureRandom import org.openrs2.crypto.secureRandom
@ -54,7 +54,7 @@ public class CreateAccountCodec @Inject constructor(
val country = plaintext.readUnsignedShort() val country = plaintext.readUnsignedShort()
val k3 = plaintext.readInt() val k3 = plaintext.readInt()
val xteaKey = XteaKey(k0, k1, k2, k3) val xteaKey = SymmetricKey(k0, k1, k2, k3)
input.xteaDecrypt(input.readerIndex(), input.readableBytes(), xteaKey) input.xteaDecrypt(input.readerIndex(), input.readableBytes(), xteaKey)
val email = input.readString() val email = input.readString()
@ -84,7 +84,7 @@ public class CreateAccountCodec @Inject constructor(
} }
override fun encode(input: LoginRequest.CreateAccount, output: ByteBuf, cipher: StreamCipher) { override fun encode(input: LoginRequest.CreateAccount, output: ByteBuf, cipher: StreamCipher) {
val xteaKey = XteaKey.generate() val xteaKey = SymmetricKey.generate()
output.writeShort(input.build) output.writeShort(input.build)

@ -6,7 +6,7 @@ import org.openrs2.buffer.readString
import org.openrs2.buffer.use import org.openrs2.buffer.use
import org.openrs2.buffer.writeString import org.openrs2.buffer.writeString
import org.openrs2.crypto.Rsa import org.openrs2.crypto.Rsa
import org.openrs2.crypto.XteaKey import org.openrs2.crypto.SymmetricKey
import org.openrs2.crypto.rsa import org.openrs2.crypto.rsa
import org.openrs2.protocol.common.AntiAliasingMode import org.openrs2.protocol.common.AntiAliasingMode
import org.openrs2.protocol.common.DisplayMode import org.openrs2.protocol.common.DisplayMode
@ -28,7 +28,7 @@ public data class GameLoginPayload(
val verifyId: Int, val verifyId: Int,
val js5ArchiveChecksums: List<Int>, val js5ArchiveChecksums: List<Int>,
// TODO(gpe): XteaKey needs a better name, as it represents an ISAAC key here // TODO(gpe): XteaKey needs a better name, as it represents an ISAAC key here
val key: XteaKey, val key: SymmetricKey,
val username: String, val username: String,
val password: String, val password: String,
) { ) {
@ -133,7 +133,7 @@ public data class GameLoginPayload(
detailOptions, detailOptions,
verifyId, verifyId,
js5ArchiveChecksums, js5ArchiveChecksums,
XteaKey(k0, k1, k2, k3), SymmetricKey(k0, k1, k2, k3),
Base37.decodeLowerCase(username), Base37.decodeLowerCase(username),
password, password,
) )

Loading…
Cancel
Save