package net.minecraft.util; import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.EncodedKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class CryptManager { private static final Logger LOGGER = LogManager.getLogger(); /** * Generate a new shared secret AES key from a secure random source */ @SideOnly(Side.CLIENT) public static SecretKey createNewSharedKey() { try { KeyGenerator keygenerator = KeyGenerator.getInstance("AES"); keygenerator.init(128); return keygenerator.generateKey(); } catch (NoSuchAlgorithmException nosuchalgorithmexception) { throw new Error(nosuchalgorithmexception); } } /** * Generates RSA KeyPair */ public static KeyPair generateKeyPair() { try { KeyPairGenerator keypairgenerator = KeyPairGenerator.getInstance("RSA"); keypairgenerator.initialize(1024); return keypairgenerator.generateKeyPair(); } catch (NoSuchAlgorithmException nosuchalgorithmexception) { nosuchalgorithmexception.printStackTrace(); LOGGER.error("Key pair generation failed!"); return null; } } /** * Compute a serverId hash for use by sendSessionRequest() */ public static byte[] getServerIdHash(String serverId, PublicKey publicKey, SecretKey secretKey) { try { return digestOperation("SHA-1", serverId.getBytes("ISO_8859_1"), secretKey.getEncoded(), publicKey.getEncoded()); } catch (UnsupportedEncodingException unsupportedencodingexception) { unsupportedencodingexception.printStackTrace(); return null; } } /** * Compute a message digest on arbitrary byte[] data */ private static byte[] digestOperation(String algorithm, byte[]... data) { try { MessageDigest messagedigest = MessageDigest.getInstance(algorithm); for (byte[] abyte : data) { messagedigest.update(abyte); } return messagedigest.digest(); } catch (NoSuchAlgorithmException nosuchalgorithmexception) { nosuchalgorithmexception.printStackTrace(); return null; } } /** * Create a new PublicKey from encoded X.509 data */ public static PublicKey decodePublicKey(byte[] encodedKey) { try { EncodedKeySpec encodedkeyspec = new X509EncodedKeySpec(encodedKey); KeyFactory keyfactory = KeyFactory.getInstance("RSA"); return keyfactory.generatePublic(encodedkeyspec); } catch (NoSuchAlgorithmException var3) { ; } catch (InvalidKeySpecException var4) { ; } LOGGER.error("Public key reconstitute failed!"); return null; } /** * Decrypt shared secret AES key using RSA private key */ public static SecretKey decryptSharedKey(PrivateKey key, byte[] secretKeyEncrypted) { return new SecretKeySpec(decryptData(key, secretKeyEncrypted), "AES"); } /** * Encrypt byte[] data with RSA public key */ @SideOnly(Side.CLIENT) public static byte[] encryptData(Key key, byte[] data) { return cipherOperation(1, key, data); } /** * Decrypt byte[] data with RSA private key */ public static byte[] decryptData(Key key, byte[] data) { return cipherOperation(2, key, data); } /** * Encrypt or decrypt byte[] data using the specified key */ private static byte[] cipherOperation(int opMode, Key key, byte[] data) { try { return createTheCipherInstance(opMode, key.getAlgorithm(), key).doFinal(data); } catch (IllegalBlockSizeException illegalblocksizeexception) { illegalblocksizeexception.printStackTrace(); } catch (BadPaddingException badpaddingexception) { badpaddingexception.printStackTrace(); } LOGGER.error("Cipher data failed!"); return null; } /** * Creates the Cipher Instance. */ private static Cipher createTheCipherInstance(int opMode, String transformation, Key key) { try { Cipher cipher = Cipher.getInstance(transformation); cipher.init(opMode, key); return cipher; } catch (InvalidKeyException invalidkeyexception) { invalidkeyexception.printStackTrace(); } catch (NoSuchAlgorithmException nosuchalgorithmexception) { nosuchalgorithmexception.printStackTrace(); } catch (NoSuchPaddingException nosuchpaddingexception) { nosuchpaddingexception.printStackTrace(); } LOGGER.error("Cipher creation failed!"); return null; } /** * Creates an Cipher instance using the AES/CFB8/NoPadding algorithm. Used for protocol encryption. */ public static Cipher createNetCipherInstance(int opMode, Key key) { try { Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding"); cipher.init(opMode, key, new IvParameterSpec(key.getEncoded())); return cipher; } catch (GeneralSecurityException generalsecurityexception) { throw new RuntimeException(generalsecurityexception); } } }