1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
package kr.syeyoung.dungeonsguide;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import lombok.Getter;
import net.minecraft.client.Minecraft;
import net.minecraft.util.Session;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.*;
import java.security.*;
import java.util.UUID;
public class Authenticator {
@Getter
private KeyPair keyPair;
@Getter
private String token;
private KeyPair generate1024RSAKey() {
KeyPairGenerator generator = null;
try {
generator = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
generator.initialize(1024);
keyPair = generator.generateKeyPair();
return keyPair;
}
public Authenticator() {
generate1024RSAKey();
}
private static final String DOMAIN = "http://localhost:8080/";
public String authenticate() throws IOException, AuthenticationException, NoSuchAlgorithmException {
Session session = Minecraft.getMinecraft().getSession();
String token = session.getToken();
String jwt = requestAuth(session.getProfile());
MinecraftSessionService yggdrasilMinecraftSessionService = Minecraft.getMinecraft().getSessionService();
JsonObject jwt2 = parseJWT(jwt);
String hash = calculateAuthHash(DatatypeConverter.parseBase64Binary(jwt2.get("sharedSecret").getAsString()),
DatatypeConverter.parseBase64Binary(jwt2.get("publicKey").getAsString()));
yggdrasilMinecraftSessionService.joinServer(session.getProfile(), token, hash);
this.token = requestAuth2(jwt, keyPair.getPublic());
return this.token;
}
public JsonObject parseJWT(String jwt) {
String payload = jwt.split("\\.")[1].replace("+", "-").replace("/", "_");
String json = new String(DatatypeConverter.parseBase64Binary(payload));
return (JsonObject) new JsonParser().parse(json);
}
private String requestAuth(GameProfile profile) throws IOException {
HttpURLConnection huc = (HttpURLConnection) new URL(DOMAIN+"auth/requestAuth").openConnection();
huc.setRequestProperty("User-Agent", "DungeonsGuide/1.0");
huc.setRequestProperty("Content-Type", "application/json");
huc.setRequestMethod("POST");
huc.setDoInput(true);
huc.setDoOutput(true);
huc.getOutputStream().write(("{\"uuid\":\""+profile.getId().toString()+"\",\"nickname\":\""+profile.getName()+"\"}").getBytes());
InputStreamReader inputStreamReader = new InputStreamReader(huc.getInputStream());
JsonObject object = (JsonObject) new JsonParser().parse(inputStreamReader);
if (!"ok".equals(object.get("status").getAsString())) {
return null;
}
return object.get("data").getAsString();
}
private String requestAuth2(String token, PublicKey publicKey) throws IOException {
HttpURLConnection huc = (HttpURLConnection) new URL(DOMAIN+"auth/authenticate").openConnection();
huc.setRequestMethod("POST");
huc.setRequestProperty("User-Agent", "DungeonsGuide/1.0");
huc.setRequestProperty("Content-Type", "application/json");
huc.setDoInput(true);
huc.setDoOutput(true);
huc.getOutputStream().write(("{\"jwt\":\""+token+"\",\"publicKey\":\""+DatatypeConverter.printBase64Binary(publicKey.getEncoded())+"\"}").getBytes());
InputStreamReader inputStreamReader = new InputStreamReader(huc.getInputStream());
JsonObject object = (JsonObject) new JsonParser().parse(inputStreamReader);
if (!"ok".equals(object.get("status").getAsString())) {
return null;
}
return object.get("data").getAsString();
}
public String calculateAuthHash(byte[] sharedSecret, byte[] pk) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update("".getBytes());
md.update(sharedSecret);
md.update(pk);
byte[] result = md.digest();
return new BigInteger(result).toString(16);
}
}
|