From d05c005b395a8c7bd5138b06045c526a0c1881bb Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Fri, 1 May 2020 00:47:52 +0800 Subject: [PATCH] Reimplement signing key injection --- .../authlibinjector/AuthlibInjector.java | 2 +- .../support/YggdrasilKeyTransformUnit.java | 95 ++++--------------- 2 files changed, 17 insertions(+), 80 deletions(-) diff --git a/src/main/java/moe/yushi/authlibinjector/AuthlibInjector.java b/src/main/java/moe/yushi/authlibinjector/AuthlibInjector.java index b92df4c..897c3b4 100644 --- a/src/main/java/moe/yushi/authlibinjector/AuthlibInjector.java +++ b/src/main/java/moe/yushi/authlibinjector/AuthlibInjector.java @@ -457,7 +457,7 @@ public final class AuthlibInjector { SkinWhitelistTransformUnit.getWhitelistedDomains().addAll(config.getSkinDomains()); transformer.units.add(new YggdrasilKeyTransformUnit()); - config.getDecodedPublickey().ifPresent(YggdrasilKeyTransformUnit.getPublicKeys()::add); + config.getDecodedPublickey().ifPresent(YggdrasilKeyTransformUnit.PUBLIC_KEYS::add); return transformer; } diff --git a/src/main/java/moe/yushi/authlibinjector/transform/support/YggdrasilKeyTransformUnit.java b/src/main/java/moe/yushi/authlibinjector/transform/support/YggdrasilKeyTransformUnit.java index 7dd8649..0399e41 100644 --- a/src/main/java/moe/yushi/authlibinjector/transform/support/YggdrasilKeyTransformUnit.java +++ b/src/main/java/moe/yushi/authlibinjector/transform/support/YggdrasilKeyTransformUnit.java @@ -16,34 +16,17 @@ */ package moe.yushi.authlibinjector.transform.support; -import static org.objectweb.asm.Opcodes.ACC_PRIVATE; -import static org.objectweb.asm.Opcodes.ACC_STATIC; -import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC; -import static org.objectweb.asm.Opcodes.ALOAD; import static org.objectweb.asm.Opcodes.ASM7; -import static org.objectweb.asm.Opcodes.ASTORE; -import static org.objectweb.asm.Opcodes.CHECKCAST; -import static org.objectweb.asm.Opcodes.F_APPEND; -import static org.objectweb.asm.Opcodes.F_CHOP; -import static org.objectweb.asm.Opcodes.F_SAME; -import static org.objectweb.asm.Opcodes.GOTO; -import static org.objectweb.asm.Opcodes.ICONST_0; -import static org.objectweb.asm.Opcodes.ICONST_1; -import static org.objectweb.asm.Opcodes.IFEQ; -import static org.objectweb.asm.Opcodes.INVOKEINTERFACE; -import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.H_INVOKEVIRTUAL; import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; -import static org.objectweb.asm.Opcodes.IRETURN; - +import java.lang.invoke.MethodHandle; import java.security.PublicKey; import java.util.List; import java.util.Optional; import java.util.concurrent.CopyOnWriteArrayList; - import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; +import org.objectweb.asm.Handle; import org.objectweb.asm.MethodVisitor; - import moe.yushi.authlibinjector.transform.CallbackMethod; import moe.yushi.authlibinjector.transform.CallbackSupport; import moe.yushi.authlibinjector.transform.TransformContext; @@ -51,68 +34,25 @@ import moe.yushi.authlibinjector.transform.TransformUnit; public class YggdrasilKeyTransformUnit implements TransformUnit { - private static final List PUBLIC_KEYS = new CopyOnWriteArrayList<>(); + public static final List PUBLIC_KEYS = new CopyOnWriteArrayList<>(); @CallbackMethod - public static List getPublicKeys() { - return PUBLIC_KEYS; + public static boolean verifyPropertySignature(Object property, PublicKey mojangKey, MethodHandle verifyAction) throws Throwable { + if ((boolean) verifyAction.invoke(property, mojangKey)) { + return true; + } + for (PublicKey customKey : PUBLIC_KEYS) { + if ((boolean) verifyAction.invoke(property, customKey)) { + return true; + } + } + return false; } @Override public Optional transform(ClassLoader classLoader, String className, ClassVisitor writer, TransformContext ctx) { if ("com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService".equals(className)) { return Optional.of(new ClassVisitor(ASM7, writer) { - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, name, signature, superName, interfaces); - - MethodVisitor mv = super.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, - "authlib_injector_isSignatureValid", - "(Lcom/mojang/authlib/properties/Property;Ljava/security/PublicKey;)Z", - null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, "com/mojang/authlib/properties/Property", "isSignatureValid", "(Ljava/security/PublicKey;)Z", false); - Label l0 = new Label(); - mv.visitJumpInsn(IFEQ, l0); - mv.visitInsn(ICONST_1); - mv.visitInsn(IRETURN); - mv.visitLabel(l0); - mv.visitFrame(F_SAME, 0, null, 0, null); - CallbackSupport.invoke(ctx, mv, YggdrasilKeyTransformUnit.class, "getPublicKeys"); - mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "iterator", "()Ljava/util/Iterator;", true); - mv.visitVarInsn(ASTORE, 2); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitFrame(F_APPEND, 1, new Object[] { "java/util/Iterator" }, 0, null); - mv.visitVarInsn(ALOAD, 2); - mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true); - Label l2 = new Label(); - mv.visitJumpInsn(IFEQ, l2); - mv.visitVarInsn(ALOAD, 2); - mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true); - mv.visitTypeInsn(CHECKCAST, "java/security/PublicKey"); - mv.visitVarInsn(ASTORE, 3); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 3); - mv.visitMethodInsn(INVOKEVIRTUAL, "com/mojang/authlib/properties/Property", "isSignatureValid", "(Ljava/security/PublicKey;)Z", false); - Label l3 = new Label(); - mv.visitJumpInsn(IFEQ, l3); - mv.visitInsn(ICONST_1); - mv.visitInsn(IRETURN); - mv.visitLabel(l3); - mv.visitFrame(F_SAME, 0, null, 0, null); - mv.visitJumpInsn(GOTO, l1); - mv.visitLabel(l2); - mv.visitFrame(F_CHOP, 1, null, 0, null); - mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); - mv.visitMaxs(-1, -1); - mv.visitEnd(); - } - @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { return new MethodVisitor(ASM7, super.visitMethod(access, name, desc, signature, exceptions)) { @@ -123,11 +63,8 @@ public class YggdrasilKeyTransformUnit implements TransformUnit { && "isSignatureValid".equals(name) && "(Ljava/security/PublicKey;)Z".equals(descriptor)) { ctx.markModified(); - super.visitMethodInsn(INVOKESTATIC, - "com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService", - "authlib_injector_isSignatureValid", - "(Lcom/mojang/authlib/properties/Property;Ljava/security/PublicKey;)Z", - false); + super.visitLdcInsn(new Handle(H_INVOKEVIRTUAL, owner, name, descriptor, isInterface)); + CallbackSupport.invoke(ctx, this, YggdrasilKeyTransformUnit.class, "verifyPropertySignature"); } else { super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); }