001 package net.minecraft.util; 002 003 import cpw.mods.fml.common.asm.ReobfuscationMarker; 004 import cpw.mods.fml.relauncher.Side; 005 import cpw.mods.fml.relauncher.SideOnly; 006 import java.io.InputStream; 007 import java.io.OutputStream; 008 import java.io.UnsupportedEncodingException; 009 import java.nio.charset.Charset; 010 import java.security.InvalidKeyException; 011 import java.security.Key; 012 import java.security.KeyFactory; 013 import java.security.KeyPair; 014 import java.security.KeyPairGenerator; 015 import java.security.MessageDigest; 016 import java.security.NoSuchAlgorithmException; 017 import java.security.PrivateKey; 018 import java.security.PublicKey; 019 import java.security.SecureRandom; 020 import java.security.Security; 021 import java.security.spec.InvalidKeySpecException; 022 import java.security.spec.X509EncodedKeySpec; 023 import javax.crypto.BadPaddingException; 024 import javax.crypto.Cipher; 025 import javax.crypto.IllegalBlockSizeException; 026 import javax.crypto.NoSuchPaddingException; 027 import javax.crypto.SecretKey; 028 import javax.crypto.spec.SecretKeySpec; 029 import org.bouncycastle.crypto.BufferedBlockCipher; 030 import org.bouncycastle.crypto.CipherKeyGenerator; 031 import org.bouncycastle.crypto.KeyGenerationParameters; 032 import org.bouncycastle.crypto.engines.AESFastEngine; 033 import org.bouncycastle.crypto.io.CipherInputStream; 034 import org.bouncycastle.crypto.io.CipherOutputStream; 035 import org.bouncycastle.crypto.modes.CFBBlockCipher; 036 import org.bouncycastle.crypto.params.KeyParameter; 037 import org.bouncycastle.crypto.params.ParametersWithIV; 038 import org.bouncycastle.jce.provider.BouncyCastleProvider; 039 040 @ReobfuscationMarker 041 public class CryptManager 042 { 043 /** ISO_8859_1 */ 044 public static final Charset charSet = Charset.forName("ISO_8859_1"); 045 046 @SideOnly(Side.CLIENT) 047 048 /** 049 * Generate a new shared secret AES key from a secure random source 050 */ 051 public static SecretKey createNewSharedKey() 052 { 053 CipherKeyGenerator var0 = new CipherKeyGenerator(); 054 var0.init(new KeyGenerationParameters(new SecureRandom(), 128)); 055 return new SecretKeySpec(var0.generateKey(), "AES"); 056 } 057 058 public static KeyPair createNewKeyPair() 059 { 060 try 061 { 062 KeyPairGenerator var0 = KeyPairGenerator.getInstance("RSA"); 063 var0.initialize(1024); 064 return var0.generateKeyPair(); 065 } 066 catch (NoSuchAlgorithmException var1) 067 { 068 var1.printStackTrace(); 069 System.err.println("Key pair generation failed!"); 070 return null; 071 } 072 } 073 074 /** 075 * Compute a serverId hash for use by sendSessionRequest() 076 */ 077 public static byte[] getServerIdHash(String par0Str, PublicKey par1PublicKey, SecretKey par2SecretKey) 078 { 079 try 080 { 081 return digestOperation("SHA-1", new byte[][] {par0Str.getBytes("ISO_8859_1"), par2SecretKey.getEncoded(), par1PublicKey.getEncoded()}); 082 } 083 catch (UnsupportedEncodingException var4) 084 { 085 var4.printStackTrace(); 086 return null; 087 } 088 } 089 090 /** 091 * Compute a message digest on arbitrary byte[] data 092 */ 093 private static byte[] digestOperation(String par0Str, byte[] ... par1ArrayOfByte) 094 { 095 try 096 { 097 MessageDigest var2 = MessageDigest.getInstance(par0Str); 098 byte[][] var3 = par1ArrayOfByte; 099 int var4 = par1ArrayOfByte.length; 100 101 for (int var5 = 0; var5 < var4; ++var5) 102 { 103 byte[] var6 = var3[var5]; 104 var2.update(var6); 105 } 106 107 return var2.digest(); 108 } 109 catch (NoSuchAlgorithmException var7) 110 { 111 var7.printStackTrace(); 112 return null; 113 } 114 } 115 116 /** 117 * Create a new PublicKey from encoded X.509 data 118 */ 119 public static PublicKey decodePublicKey(byte[] par0ArrayOfByte) 120 { 121 try 122 { 123 X509EncodedKeySpec var1 = new X509EncodedKeySpec(par0ArrayOfByte); 124 KeyFactory var2 = KeyFactory.getInstance("RSA"); 125 return var2.generatePublic(var1); 126 } 127 catch (NoSuchAlgorithmException var3) 128 { 129 var3.printStackTrace(); 130 } 131 catch (InvalidKeySpecException var4) 132 { 133 var4.printStackTrace(); 134 } 135 136 System.err.println("Public key reconstitute failed!"); 137 return null; 138 } 139 140 /** 141 * Decrypt shared secret AES key using RSA private key 142 */ 143 public static SecretKey decryptSharedKey(PrivateKey par0PrivateKey, byte[] par1ArrayOfByte) 144 { 145 return new SecretKeySpec(decryptData(par0PrivateKey, par1ArrayOfByte), "AES"); 146 } 147 148 @SideOnly(Side.CLIENT) 149 150 /** 151 * Encrypt byte[] data with RSA public key 152 */ 153 public static byte[] encryptData(Key par0Key, byte[] par1ArrayOfByte) 154 { 155 return cipherOperation(1, par0Key, par1ArrayOfByte); 156 } 157 158 /** 159 * Decrypt byte[] data with RSA private key 160 */ 161 public static byte[] decryptData(Key par0Key, byte[] par1ArrayOfByte) 162 { 163 return cipherOperation(2, par0Key, par1ArrayOfByte); 164 } 165 166 /** 167 * Encrypt or decrypt byte[] data using the specified key 168 */ 169 private static byte[] cipherOperation(int par0, Key par1Key, byte[] par2ArrayOfByte) 170 { 171 try 172 { 173 return createTheCipherInstance(par0, par1Key.getAlgorithm(), par1Key).doFinal(par2ArrayOfByte); 174 } 175 catch (IllegalBlockSizeException var4) 176 { 177 var4.printStackTrace(); 178 } 179 catch (BadPaddingException var5) 180 { 181 var5.printStackTrace(); 182 } 183 184 System.err.println("Cipher data failed!"); 185 return null; 186 } 187 188 /** 189 * Creates the Cipher Instance. 190 */ 191 private static Cipher createTheCipherInstance(int par0, String par1Str, Key par2Key) 192 { 193 try 194 { 195 Cipher var3 = Cipher.getInstance(par1Str); 196 var3.init(par0, par2Key); 197 return var3; 198 } 199 catch (InvalidKeyException var4) 200 { 201 var4.printStackTrace(); 202 } 203 catch (NoSuchAlgorithmException var5) 204 { 205 var5.printStackTrace(); 206 } 207 catch (NoSuchPaddingException var6) 208 { 209 var6.printStackTrace(); 210 } 211 212 System.err.println("Cipher creation failed!"); 213 return null; 214 } 215 216 /** 217 * Create a new BufferedBlockCipher instance 218 */ 219 private static BufferedBlockCipher createBufferedBlockCipher(boolean par0, Key par1Key) 220 { 221 BufferedBlockCipher var2 = new BufferedBlockCipher(new CFBBlockCipher(new AESFastEngine(), 8)); 222 var2.init(par0, new ParametersWithIV(new KeyParameter(par1Key.getEncoded()), par1Key.getEncoded(), 0, 16)); 223 return var2; 224 } 225 226 public static OutputStream encryptOuputStream(SecretKey par0SecretKey, OutputStream par1OutputStream) 227 { 228 return new CipherOutputStream(par1OutputStream, createBufferedBlockCipher(true, par0SecretKey)); 229 } 230 231 public static InputStream decryptInputStream(SecretKey par0SecretKey, InputStream par1InputStream) 232 { 233 return new CipherInputStream(par1InputStream, createBufferedBlockCipher(false, par0SecretKey)); 234 } 235 236 static 237 { 238 Security.addProvider(new BouncyCastleProvider()); 239 } 240 }