Arcturus-Community/src/main/java/com/eu/habbo/crypto/HabboDiffieHellman.java
2020-05-04 19:54:07 +02:00

109 lines
3.6 KiB
Java

package com.eu.habbo.crypto;
import com.eu.habbo.crypto.exceptions.HabboCryptoException;
import com.eu.habbo.crypto.utils.BigIntegerUtils;
import com.eu.habbo.util.HexUtils;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ThreadLocalRandom;
public class HabboDiffieHellman {
private static final int DH_PRIMES_BIT_SIZE = 128;
private static final int DH_KEY_BIT_SIZE = 128;
private final HabboRSACrypto crypto;
private BigInteger DHPrime;
private BigInteger DHGenerator;
private BigInteger DHPrivate;
private BigInteger DHPublic;
public HabboDiffieHellman(HabboRSACrypto crypto) {
this.crypto = crypto;
this.generateDHPrimes();
this.generateDHKeys();
}
public BigInteger getDHPrime() {
return DHPrime;
}
public BigInteger getDHGenerator() {
return DHGenerator;
}
private void generateDHPrimes() {
this.DHPrime = BigInteger.probablePrime(DH_PRIMES_BIT_SIZE, ThreadLocalRandom.current());
this.DHGenerator = BigInteger.probablePrime(DH_PRIMES_BIT_SIZE, ThreadLocalRandom.current());
if (this.DHGenerator.compareTo(this.DHPrime) > 0) {
BigInteger temp = this.DHPrime;
this.DHPrime = this.DHGenerator;
this.DHGenerator = temp;
}
}
private void generateDHKeys() {
this.DHPrivate = BigInteger.probablePrime(DH_KEY_BIT_SIZE, ThreadLocalRandom.current());
this.DHPublic = this.DHGenerator.modPow(this.DHPrivate, this.DHPrime);
}
private String encryptBigInteger(BigInteger integer) throws HabboCryptoException {
String str = integer.toString(10);
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
byte[] encrypted = this.crypto.Sign(bytes);
return HexUtils.toHex(encrypted).toLowerCase();
}
private BigInteger decryptBigInteger(String str) throws HabboCryptoException {
byte[] bytes = HexUtils.toBytes(str);
byte[] decrypted = this.crypto.Decrypt(bytes);
String intStr = new String(decrypted, StandardCharsets.UTF_8);
return new BigInteger(intStr, 10);
}
public String getPublicKey() throws HabboCryptoException {
return encryptBigInteger(this.DHPublic);
}
public String getSignedPrime() throws HabboCryptoException {
return encryptBigInteger(this.DHPrime);
}
public String getSignedGenerator() throws HabboCryptoException {
return encryptBigInteger(this.DHGenerator);
}
public void doHandshake(String signedPrime, String signedGenerator) throws HabboCryptoException {
this.DHPrime = decryptBigInteger(signedPrime);
this.DHGenerator = decryptBigInteger(signedGenerator);
if (this.DHPrime == null || this.DHGenerator == null) {
throw new HabboCryptoException("DHPrime or DHGenerator was null.");
}
if (this.DHPrime.compareTo(BigInteger.valueOf(2)) < 1) {
throw new HabboCryptoException("Prime cannot be <= 2!\nPrime: " + this.DHPrime.toString());
}
if (this.DHGenerator.compareTo(this.DHPrime) > -1) {
throw new HabboCryptoException("Generator cannot be >= Prime!\nPrime: " + this.DHPrime.toString() + "\nGenerator: " + this.DHGenerator.toString());
}
generateDHKeys();
}
public byte[] getSharedKey(String publicKeyStr) throws HabboCryptoException {
BigInteger publicKey = this.decryptBigInteger(publicKeyStr);
BigInteger sharedKey = publicKey.modPow(this.DHPrivate, this.DHPrime);
return BigIntegerUtils.toUnsignedByteArray(sharedKey);
}
}