Cryptography

S

Scooter

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.
 
A

Arne Vajhøj

Scooter said:
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.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 = 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 >> 4) & 0x0F));
sb.append(Integer.toHexString(ba & 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 = (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);
}
}
 
A

Arne Vajhøj

rossum said:
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
 
S

Scooter

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();
 
A

Arne Vajhøj

Scooter said:
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.

MessageDigest md = MessageDigest.getInstance("SHA-256");

will give you SHA-256.

At least in newer Jav aversions. It may be missing in older
versions - in which case you will need to use BouncyCastele
to get it.
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.

Cipher aes = Cipher.getInstance("AES");
aes.init(mode, new SecretKeySpec(key.getBytes("UTF-8"), "AES"));

will use the String key as key.

Arne
 
S

Scooter

That works until the end. the Cipher.init method is expecting a type
"Key" or "Certificate" as the second parameter. I'm sort of back to
where I started in trying to figure out how a key is created based off
of my random string SHA256 HASH. Passing that byte array caused it to
choke. And again, thanks for the info provided so far.
 
S

Scooter

I'm a step further now. I'm using the code from rossum but with some
updates to create a key from my string

....
//aesCrypt.init(Cipher.ENCRYPT_MODE, aesKey, aesParameters);
//aesDecrypt.init(Cipher.DECRYPT_MODE, aesKey, aesParameters);

SecretKeySpec aesKeySpec = new SecretKeySpec(aesKey,
0,aesKey.length,"AES");
aesCrypt.init(Cipher.ENCRYPT_MODE, aesKeySpec, aesParameters);
aesDecrypt.init(Cipher.DECRYPT_MODE, aesKeySpec, aesParameters);

Doing that I get an "Illegal key size" exception

Do do I need to do this (and this again is going back to the code from
rossum):
byte[] aesKey = sha256.digest("A Random String".toLowerCase().getBytes
());
final int BLOCK_BYTES = 16;
byte[] padKey = new byte[BLOCK_BYTES];
System.arraycopy(aesKey,0,padKey,0,BLOCK_BYTES);
SecretKeySpec aesKeySpec = new SecretKeySpec(padKey,
0,padKey.length,"AES");

I'm asking because while that does eliminate the key size error, then
in my decryption I'm getting a padding error
but that could be something else

//yes I need to replace this with something other than sun.misc
//we base64encode or encrypted value so we need to decode it first
byte[] inputBuffer=new sun.misc.BASE64Decoder().decodeBuffer
(EncryptedValue);
//this throws 'Given final block not properly padded'
byte[] buffer = aesDecrypt.doFinal(inputBuffer,0,inputBuffer.length);
 
A

Arne Vajhøj

Scooter said:
I'm a step further now. I'm using the code from rossum but with some
updates to create a key from my string

...
//aesCrypt.init(Cipher.ENCRYPT_MODE, aesKey, aesParameters);
//aesDecrypt.init(Cipher.DECRYPT_MODE, aesKey, aesParameters);

SecretKeySpec aesKeySpec = new SecretKeySpec(aesKey,
0,aesKey.length,"AES");
aesCrypt.init(Cipher.ENCRYPT_MODE, aesKeySpec, aesParameters);
aesDecrypt.init(Cipher.DECRYPT_MODE, aesKeySpec, aesParameters);

Doing that I get an "Illegal key size" exception

Do do I need to do this (and this again is going back to the code from
rossum):
byte[] aesKey = sha256.digest("A Random String".toLowerCase().getBytes
());
final int BLOCK_BYTES = 16;
byte[] padKey = new byte[BLOCK_BYTES];
System.arraycopy(aesKey,0,padKey,0,BLOCK_BYTES);
SecretKeySpec aesKeySpec = new SecretKeySpec(padKey,
0,padKey.length,"AES");
>
I'm asking because while that does eliminate the key size error, then
in my decryption I'm getting a padding error
but that could be something else

AES expects keys in 128, 192 or 256 bits = 16, 24 or 32 bytes.

You need to give a key of that length.

I don't think it is optimal to pad with zero bytes and
I am also concerned that you could get an ArrayIndexOutOfBoundsException
with that code.

Your decryption error is due to something else.

Arne
 
S

Scooter

I'm about to throw in the towel on this stuff. I think I just need to
sit down with a cryptography book..or someone that knows what their
doing. In testing my encryption values between c# and java I'm getting
different values.

Again here's the c# code :
protected internal ICryptoTransform m_objCrypt;
protected internal ICryptoTransform m_objDecrypt;

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();


protected internal String EncryptValue(String Value)
{

if (Value.Length >= MAX_QUERY_LENGTH)
{
throw new ValueException();
}

byte[] byaRawText = new System.Text.ASCIIEncoding().GetBytes
(Value);
byte[] byaCipherText = m_objCrypt.TransformFinalBlock(byaRawText,
0, byaRawText.Length);

return Convert.ToBase64String(byaCipherText);

}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
heres my java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

protected static Cipher m_objCrypt;
protected static Cipher m_objDecrypt;



try {
m_objCrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
m_objDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MessageDigest sha256 = null;
try {
sha256 = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] aesKey = sha256.digest("A Random String".toLowerCase().getBytes
());
//printhash(aesKey);

// Sets up a 128 bit (16 byte) IV for CBC mode
final int BLOCK_BYTES = 16;
byte[] aesPaddedKey = new byte[BLOCK_BYTES];
System.arraycopy(aesKey,0,aesPaddedKey,0,BLOCK_BYTES);
sha256.reset();
byte[] fullSHA = sha256.digest("3rfdfh6y-34rt-3rkl-9ijh-
mg94kgjdhsg3".toLowerCase().getBytes());
//printhash(fullSHA);
byte[] aesIV = new byte[BLOCK_BYTES];
System.arraycopy(fullSHA, 0, aesIV, 0, BLOCK_BYTES);

// Set up the IV and two cipher objects, one to encrypt and
// one to decrypt:
IvParameterSpec aesParameterSpec = new IvParameterSpec(aesIV);
AlgorithmParameters aesParameters = AlgorithmParameters.getInstance
("AES");
aesParameters.init(aesParameterSpec);

// And this is where it bombs because it expects argument2
// to be a key or certificate
//SecretKeySpec aesKeySpec = new SecretKeySpec(aesKey,
0,aesKey.length,"AES");
//Replaced with this one that uses a bytearray as a key
SecretKeySpec aesKeySpec = new SecretKeySpec(aesPaddedKey,
0,aesPaddedKey.length,"AES");
//aesCrypt.init(Cipher.ENCRYPT_MODE, aesKey, aesParameters);
//aesDecrypt.init(Cipher.DECRYPT_MODE, aesKey, aesParameters);


m_objCrypt.init(Cipher.ENCRYPT_MODE, aesKeySpec, aesParameters);
m_objDecrypt.init(Cipher.DECRYPT_MODE, aesKeySpec, aesParameters);


public String EncryptValue(String Value) {

String returnValue = null;
if (Value.length() >= MAX_QUERY_LENGTH)
{
try {
throw new Exception();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

byte[] byaRawText = null;
try {
byaRawText = Value.getBytes("US-ASCII");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
byte[] byaCipherText = null;
try {
byaCipherText = m_objCrypt.doFinal(byaRawText, 0,
byaRawText.length);
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


returnValue = b64encode(byaCipherText);
System.out.println("base 64d ok");



return returnValue;

}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thanks in advance. I know this is a lot to ask someone to look at.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,037
Latest member
MozzGuardBugs

Latest Threads

Top