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 }