Cryptography

Discussion in 'Java' started by Scooter, Nov 17, 2008.

  1. Scooter

    Scooter Guest

    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.
    Scooter, Nov 17, 2008
    #1
    1. Advertising

  2. Scooter

    Arne Vajhøj Guest

    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.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);
    }
    }
    Arne Vajhøj, Nov 18, 2008
    #2
    1. Advertising

  3. Scooter

    Arne Vajhøj Guest

    rossum wrote:
    > On Mon, 17 Nov 2008 11:58:47 -0800 (PST), Scooter
    > <> 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
    Arne Vajhøj, Nov 18, 2008
    #3
  4. Scooter

    Scooter Guest

    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();
    Scooter, Nov 18, 2008
    #4
  5. Scooter

    Arne Vajhøj Guest

    Scooter wrote:
    > 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
    Arne Vajhøj, Nov 18, 2008
    #5
  6. Scooter

    Scooter Guest

    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.
    Scooter, Nov 19, 2008
    #6
  7. Scooter

    Scooter Guest

    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);
    Scooter, Nov 19, 2008
    #7
  8. Scooter

    Arne Vajhøj Guest

    Scooter wrote:
    > 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
    Arne Vajhøj, Nov 19, 2008
    #8
  9. Scooter

    Scooter Guest

    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.
    Scooter, Nov 21, 2008
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mauricio Correa L.

    Generating hashes (System.security.cryptography)

    Mauricio Correa L., Jun 18, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    394
    Raterus
    Jun 18, 2004
  2. Dei401
    Replies:
    0
    Views:
    774
    Dei401
    Feb 2, 2005
  3. Apple

    cryptography software

    Apple, Oct 12, 2003, in forum: Java
    Replies:
    1
    Views:
    406
  4. Zheng Da
    Replies:
    2
    Views:
    376
    Zheng Da
    Apr 29, 2006
  5. Replies:
    1
    Views:
    538
    Thomas Matthews
    Nov 2, 2003
Loading...

Share This Page