From: Scooter on 17 Nov 2008 14:58 I have been tasked with writing a small java class that will decrypt a string that was encrypted with a C# app. I have the source for the C# decryption, its nothing special. I just dont know what the counterparts are in java. Heres the C# code. "m_objDecrypt" is a "ICryptoTransform" protected internal string DecryptValue(string EncryptedValue) { byte[] buffer; if (EncryptedValue.Length >= 0x800) { throw new ValueException(); } try { byte[] inputBuffer = Convert.FromBase64String(EncryptedValue); buffer = this.m_objDecrypt.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length); } catch (FormatException) { throw new ValueException(); } catch (CryptographicException) { throw new ValueException(); } return new ASCIIEncoding().GetString(buffer); } -------------------------- in my java class so far I have: byte[] buffer; if (EncryptedValue.length() >= 0x800) { } try { byte[]inputBuffer=new sun.misc.BASE64Decoder().decodeBuffer (EncryptedValue); //buffer= } catch (Exception e) { } I just have no idea about converting that whole "TransformFinalBlock" method. Any suggestions are appreciated.
From: rossum on 17 Nov 2008 15:42 On Mon, 17 Nov 2008 11:58:47 -0800 (PST), Scooter <slbentley(a)gmail.com> wrote: >I have been tasked with writing a small java class that will decrypt a >string that was encrypted with a C# app. I have the source for the C# >decryption, its nothing special. I just dont know what the >counterparts are in java. > >Heres the C# code. "m_objDecrypt" is a "ICryptoTransform" > >protected internal string DecryptValue(string EncryptedValue) >{ > byte[] buffer; > if (EncryptedValue.Length >= 0x800) > { > throw new ValueException(); > } > try > { > byte[] inputBuffer = Convert.FromBase64String(EncryptedValue); > buffer = this.m_objDecrypt.TransformFinalBlock(inputBuffer, 0, >inputBuffer.Length); > } > catch (FormatException) > { > throw new ValueException(); > } > catch (CryptographicException) > { > throw new ValueException(); > } > return new ASCIIEncoding().GetString(buffer); >} > >-------------------------- >in my java class so far I have: > > byte[] buffer; Cipher myCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); The Cipher parameters must obviously match the equivalent on the C# side: Algorithm, mode and padding method. myCipher.init(Cipher.DECRYPT_MODE, decryptionKey, otherParameters); Other parameters covers things like the IV (for CBC mode) or the nonce (for CTR mode) or whatever else is needed. > > if (EncryptedValue.length() >= 0x800) { throw new PickYourException("Decoding: buffer length exceeded."); > } > > try > { > byte[]inputBuffer=new > sun.misc.BASE64Decoder().decodeBuffer(EncryptedValue); Do not use sun.misc for any production code, it cannot be relied on. Find a decent Base64 converter on the web (there are hundreds) and either copy or import that. > //buffer= buffer = myCipher.doFinal(inputBuffer); > } > catch (Exception e) > { Cipher.doFinal() may throw IllegalStateException, IllegalBlockSizeException or BadPaddingException. Check the Javadoc for details. > } > > >I just have no idea about converting that whole "TransformFinalBlock" >method. It seems to be the equivalent of the Cipher.doFinal() methods. See the Javadoc for javax.crypto.Cipher at http://java.sun.com/javase/6/docs/api/javax/crypto/Cipher.html For a specific overview of Java cryptography have a look at the JCA Guide, particularly the section on the Cipher class: http://java.sun.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html > >Any suggestions are appreciated. HTH rossum
From: Arne Vajhøj on 17 Nov 2008 20:20 Scooter wrote: > I have been tasked with writing a small java class that will decrypt a > string that was encrypted with a C# app. I have the source for the C# > decryption, its nothing special. I just dont know what the > counterparts are in java. > > Heres the C# code. "m_objDecrypt" is a "ICryptoTransform" > > protected internal string DecryptValue(string EncryptedValue) > { > byte[] buffer; > if (EncryptedValue.Length >= 0x800) > { > throw new ValueException(); > } > try > { > byte[] inputBuffer = Convert.FromBase64String(EncryptedValue); > buffer = this.m_objDecrypt.TransformFinalBlock(inputBuffer, 0, > inputBuffer.Length); > } > catch (FormatException) > { > throw new ValueException(); > } > catch (CryptographicException) > { > throw new ValueException(); > } > return new ASCIIEncoding().GetString(buffer); > } > > -------------------------- > in my java class so far I have: > > byte[] buffer; > > if (EncryptedValue.length() >= 0x800) { > > > } > > try > { > byte[]inputBuffer=new sun.misc.BASE64Decoder().decodeBuffer > (EncryptedValue); > //buffer= > } > catch (Exception e) > { > > } > > > I just have no idea about converting that whole "TransformFinalBlock" > method. The Java equivalent to C# ICryptoTransform.TransformFinalBlock is Cipher.doFinal ! Attached below are some C# code and Java code that does the same thing. The use Hex not Base64 though. Arne =========================================== using System; using System.Globalization; using System.Text; using System.Security.Cryptography; namespace E { public class Program { public static string ToHex(byte[] ba) { StringBuilder sb = new StringBuilder(2 * ba.Length); for(int i = 0; i < ba.Length; i++) { sb.Append(ba[i].ToString("X2")); } return sb.ToString(); } public static byte[] FromHex(string s) { byte[] ba = new byte[s.Length/2]; for(int i = 0; i < ba.Length; i++) { ba[i] = byte.Parse(s.Substring(2 * i, 2), NumberStyles.HexNumber); } return ba; } public static string Encrypt(string s) { TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); tdes.Key = Encoding.UTF8.GetBytes("MySecretKeyxxxxx"); tdes.Mode = CipherMode.ECB; tdes.Padding = PaddingMode.PKCS7; ICryptoTransform crypt = tdes.CreateEncryptor(); byte[] plain = Encoding.UTF8.GetBytes(s); byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length); return ToHex(cipher); } public static string Decrypt(string s) { TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); tdes.Key = Encoding.UTF8.GetBytes("MySecretKeyxxxxx"); tdes.Mode = CipherMode.ECB; tdes.Padding = PaddingMode.PKCS7; ICryptoTransform crypt = tdes.CreateDecryptor(); byte[] cipher = FromHex(s); byte[] plain = crypt.TransformFinalBlock(cipher, 0 , cipher.Length); return Encoding.UTF8.GetString(plain); } public static void Main(string[] args) { string p1 = "Dette er en lille test ABC ��� 123 !!!!"; Console.WriteLine(p1); string c = Encrypt(p1); Console.WriteLine(c); string p2 = Decrypt(c); Console.WriteLine(p2); } } } import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.Security; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class TrippleDES { static { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } public static String encrypt(String s) throws NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { Cipher crypt = Cipher.getInstance("DESede/ECB/PKCS7Padding"); SecretKey key = new SecretKeySpec("MySecretKeyxxxxx".getBytes(), "DESede"); crypt.init(Cipher.ENCRYPT_MODE, key); byte[] plain = s.getBytes("UTF-8"); byte[] cipher = crypt.doFinal(plain, 0, plain.length); return toHex(cipher); } public static String decrypt(String s) throws NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { Cipher crypt = Cipher.getInstance("DESede/ECB/PKCS7Padding"); SecretKey key = new SecretKeySpec("MySecretKeyxxxxx".getBytes(), "DESede"); crypt.init(Cipher.DECRYPT_MODE, key); byte[] cipher = fromHex(s); byte[] plain = crypt.doFinal(cipher, 0, cipher.length); return new String(plain, "UTF-8"); } private static String toHex(byte[] ba) { StringBuffer sb = new StringBuffer(""); for (int i = 0; i < ba.length; i++) { sb.append(Integer.toHexString((ba[i] >> 4) & 0x0F)); sb.append(Integer.toHexString(ba[i] & 0x0F)); } return sb.toString(); } private static byte[] fromHex(String s) { int n = s.length() / 2; byte[] res = new byte[n]; for(int i = 0; i < n; i++) { res[i] = (byte)(Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16)); } return res; } public static void main(String[] args) throws Exception { String p1 = "Dette er en lille test ABC ��� 123 !!!!"; System.out.println(p1); String c = encrypt(p1); System.out.println(c); String p2 = decrypt(c); System.out.println(p2); } }
From: Arne Vajhøj on 17 Nov 2008 20:24 rossum wrote: > On Mon, 17 Nov 2008 11:58:47 -0800 (PST), Scooter > <slbentley(a)gmail.com> wrote: >> byte[]inputBuffer=new >> sun.misc.BASE64Decoder().decodeBuffer(EncryptedValue); > Do not use sun.misc for any production code, it cannot be relied on. Good advice. > Find a decent Base64 converter on the web (there are hundreds) and > either copy or import that. I would make that much more specific. Do not find just any Base64 implementation. Base64 is actually standardized in Java. It is just in Java EE not in Java SE. So find a standard compliant base64 implementation. JavaMail reference implementation from SUN is one possibility. Some simple wrappers to make it easier to use: public static String b64encode(byte[] b) throws MessagingException, IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream b64os = MimeUtility.encode(baos, "base64"); b64os.write(b); b64os.close(); return new String(baos.toByteArray()); } public static byte[] b64decode(String s) throws MessagingException, IOException { ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes()); InputStream b64is = MimeUtility.decode(bais, "Base64"); byte[] tmp = new byte[s.length()]; int n = b64is.read(tmp); byte[] res = new byte[n]; System.arraycopy(tmp, 0, res, 0, n); return res; } Arne
From: Scooter on 18 Nov 2008 15:15
You all have been really helpful so far, but honestly I'm swimming upstream here. I know very little about cryptography and I'm trying to learn but the light aint coming on yet. Here's the beginning of the C# code. I've been playing with KeyGenerator,SecretKey etc, but I'm not getting it. Plus I'm getting conflicting articles online about whether SHA256 is incorporated in java or not. Maybe they were all old. I can't seem to find anything where you generate a key based off of your own strings like the C# code seems to be doing. Seems like keygenerator just generates a random one. So, if you want to take the time and point me in the right direction, it would be very much appreciate. Anyway, I didn't write this, I'm just the lucky fella that has to try to convert it to java. RijndaelManaged objAesCipher = new RijndaelManaged(); objAesCipher.KeySize = 256; objAesCipher.BlockSize = 128; // has to be 128 to be AES compat objAesCipher.Mode = CipherMode.CBC; objAesCipher.Padding = PaddingMode.PKCS7; objAesCipher.Key = new System.Security.Cryptography.SHA256Managed ().ComputeHash( new ASCIIEncoding().GetBytes("A Random String".ToLower()) ); byte[] fullSHA = new System.Security.Cryptography.SHA256Managed ().ComputeHash( new ASCIIEncoding().GetBytes("3rfdfh6y-34rt-3rkl-9ijh- mg94kgjdhsg3".ToLower()) ); byte[] trimmedSHA = new byte[16]; Array.Copy(fullSHA, trimmedSHA, 16); // can only use 128 block size to be real AES objAesCipher.IV = trimmedSHA; m_objCrypt = objAesCipher.CreateEncryptor(); m_objDecrypt = objAesCipher.CreateDecryptor(); |