Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Скрыть объявление

[Решено] Скины 1.8+

Тема в разделе "Разработка плагинов для новичков", создана пользователем Reality_SC, 23 мар 2015.

Статус темы:
Закрыта.
  1. Автор темы
    Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Сервер в online-mode.
    Методы authenticate / join / hasJoined / profile переписаны на адреса моих скриптов.
    Скрипты выдают корректные профили, в том числе текстурки (скины/плащи).
    Код:
    ...,
    "textures": {
       "SKIN": {
          "url": "<действующий url скина>"
       },
    },
    ...
    В клиенте ссылки тоже заменены, вижу это по логу.

    Игрок начинает коннектиться на сервер, шлёт join, сервер запрашивает hasJoined и получает в ответ скин игрока, который отдаёт клиенту. Когда игрок видит других (spawn entity), сервер посылает их blob-ы клиенту.

    Это в теории. На практике клиент после подключения показывает дефолтную Алекс несколько секунд, потом в логе видно, что он обратился к подменённому скрипту и скачал свой скин — с этого момента каждый игрок видит свой скин, как и должно быть. Когда в поле зрения появляются другие игроки, клиент не видит их скинов, показывает всех как Алекс.

    Я грешу на проверку сигнатуры, она ведь в 1.8 обязательная?
    Код:
        @Override
        public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(GameProfile profile, boolean requireSecure)
        {
            Property textureProperty = (Property)Iterables.getFirst(profile.getProperties().get("textures"), null);
            if(textureProperty == null)
                return new HashMap();
            if(requireSecure)
            {
                if(!textureProperty.hasSignature())
                {
                    LOGGER.error("Signature is missing from textures payload");
                    throw new InsecureTextureException("Signature is missing from textures payload");
                }
                if(!textureProperty.isSignatureValid(publicKey))
                {
                    LOGGER.error("Textures payload has been tampered with (signature invalid)");
                    throw new InsecureTextureException("Textures payload has been tampered with (signature invalid)");
                }
            }
            MinecraftTexturesPayload result;
            try
            {
                String json = new String(Base64.decodeBase64(textureProperty.getValue()), Charsets.UTF_8);
                result = (MinecraftTexturesPayload)gson.fromJson(json, MinecraftTexturesPayload.class);
            } catch(JsonParseException e) {
                LOGGER.error("Could not decode textures payload", e);
                return new HashMap();
            }
    
            return result.getTextures() == null ? new HashMap() : result.getTextures();
        }
    
    Property
    Код:
    public boolean isSignatureValid(PublicKey publicKey)
    {
        try
        {
            Signature signature = Signature.getInstance("SHA1withRSA");
            signature.initVerify(publicKey);
            signature.update(value.getBytes());
            return signature.verify(Base64.decodeBase64(this.signature));
        } catch(NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
        }
        return false;
    }
    
    Что-то мне не по глазам, где именно это вызывается. Проблема в сервере, что он не принимает неподписанные скины от hasJoined, или у клиента? (хотя клиент даже не подаёт желания скачать чьи-то скины).
    Не могли бы Вы помочь найти это место?

    @Shevchik @alexandrage

    Соответсвенно, когда будет найдено место, встаёт второй вопрос: как вырезать проверку сигнатуры? Я хочу делать это в рантайме, по крайней мере на сервере 100%. Из вариантов наиболее лёгким выглядит генерация своего yggdrasil_session_pubkey.der ключа, которым буду подписывать скин на скриптах, и вставить его в сервер/клиент.
     
    Последнее редактирование: 23 мар 2015
  2. Хостинг MineCraft
    <
  3. Shevchik

    Shevchik Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    _Shevchik_
    Клиент не принимает неподписанные скины. Все скины игроку посылает сам сервер кроме своего собственного, в 1.8 - вообще все.
     
  4. Автор темы
    Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Есть идеи по вариантам, как это вырезать в рантайме?
    Я через рефлексию заменяю константные поля authlib, через подмену URLStreamHandler (стырил из твоего MojangAPIProxy) подменяю все остальные обращения клиента и сервера к Mojang API, но тут всё выглядит так, что узким местом является подмена одного из методов:
    • в HttpAuthenticationService метод getTextures(GameProfile profile, boolean requireSecure),
    • в Property метод isSignatureValid(PublicKey publicKey),
    • в Signature статический вызов getInstance("SHA1withRSA"),
    • ну либо действительно заменять ключ .der.
    Заменой методов (трансформерами, через ASM) ещё пока никогда не занимался.
    Может быть я упускаю какой-то более лёгкий способ обмана клиента?
    [DOUBLEPOST=1427115465,1427102135][/DOUBLEPOST]
    Проблема временно решена (ну мы знаем, нет ничего более постоянного ...)

    Т.к. клиенты у меня патчатся враппером, я просто добавил к нему Property-заглушку, которую сам вызываю заранее, чтобы разместить в текущем ClassLoader-е.

    Если кому-то в голову придёт ещё более простое и/или надёжное решение, прошу излагать ниже не стесняясь.
     
  5. alexandrage

    alexandrage Администратор

    Баллы:
    173
    Skype:
    alexandr0116
    Отстаешь от жизни как обычно, я уже давно пролечил аутчлибу чтоб не проверять сигну :).
    [​IMG][DOUBLEPOST=1427161402,1427160227][/DOUBLEPOST]
    А ты всегда все усложняешь, а всего то нужно передать requireSecure = false, ибо затычка от сигны уже имеется в аутчлибе. Она включается в одиночной игре.
     
    Последнее редактирование: 24 мар 2015
  6. Автор темы
    Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Отучить её не проблема, мне интересно решить задачу не трогая AuthLib :)[DOUBLEPOST=1427192248,1427171342][/DOUBLEPOST]@alexandrage, подскажи, верно ли утверждение, что ClassLoader ищет .class в перечне переданных его конструктору URL[] в порядке их следования в списке? или где-то внутри они могут быть раскидываны по Set-у и порядок осмотра более случаен?

    P.S. Тема закрыта.
     
    Последнее редактирование: 1 апр 2015
Статус темы:
Закрыта.

Поделиться этой страницей