1

I'm cobol developer but I have to develop some code in java. I'm encrypting/decrypting strings in cobol usign hexadecimal values as encryption key and XOR operation. Those encrypted data are stored on a DB and then I have to read and decrypt them in java. I have no problem using ^ (xor) in java for those data encrypted with a key from 0x00 to 0x7F, the problem is when the key is from 0x80 to 0xFF (extended ASCII). I've read some posts (post1, post2) with a similar problem but I continue with the same problem.

In my code I'm trying to decode the encrypted data using the key 0x85 (character "…" in ASCII), it should return the data "desde cobol". With sql I'm getting the encypted value in a String, but its value in hex is 0xE1, 0xE0, 0xF6, 0xE1, 0xE0, 0xA5, 0xE6, 0xEA, 0xE7, 0xEA, 0xE9. (I would like to omit the sql code, but I don't know how to convert those hex into a string). How could I get the decrypted value 'desde cobol'?

import java.io.IOException;
import java.lang.Math;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.xml.bind.DatatypeConverter;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.util.Base64;

public class Decode02 {
 public static void main(String args[]) {
    //
    Connection c = null;
    Statement stmt = null;
    String data = null;
    try {
      Class.forName("org.sqlite.JDBC");
      c = DriverManager.getConnection("jdbc:sqlite:test2.db");
      c.setAutoCommit(false);
      System.out.println("Opened database successfully");

      stmt = c.createStatement();
      ResultSet rs = stmt.executeQuery( "SELECT * FROM tabla where key = '002';" );
      while ( rs.next() ) {
         String  key = rs.getString("key");

         data = rs.getString("data");


         System.out.println( "CLAVE = " + key );
         System.out.println( "DATOS = " + data );

         System.out.println();
      }
      rs.close();
      stmt.close();
      c.close();
    } catch ( Exception e ) {
      System.err.println( e.getClass().getName() + ": " + e.getMessage() );
      System.exit(0);
    }
    System.out.println("Operation done successfully");


    String shex = "85";
    byte[] keyHex = DatatypeConverter.parseHexBinary(shex);
    System.out.println("Byte: " + keyHex[0]);

    byte[] bhex = new byte[0x85];
    String keyStr = DatatypeConverter.printHexBinary(bhex);
    System.out.println("String: " + keyStr);

    System.out.println("");

    String salida = new String(encode(data,shex));
    System.out.println("Salida: " + salida);

    String salida2 = new String(encode(data,keyStr));
    System.out.println("Salida2: " + salida2);

    System.out.println("");



 }

public static String encode(String s, String key) {
    return base64Encode(xorWithKey(s.getBytes(), key.getBytes()));
}

public static String decode(String s, String key) {
    return new String(xorWithKey(base64Decode(s), key.getBytes()));
}

private static byte[] xorWithKey(byte[] a, byte[] key) {
    byte[] out = new byte[a.length];
    for (int i = 0; i < a.length; i++) {
        out[i] = (byte) (a[i] ^ key[i%key.length]);
    }
    return out;
}

private static byte[] base64Decode(String s) {
    try {
        BASE64Decoder d = new BASE64Decoder();
        return d.decodeBuffer(s);
    } catch (IOException e) {throw new RuntimeException(e);}
}

private static String base64Encode(byte[] bytes) {
    BASE64Encoder enc = new BASE64Encoder();
    return enc.encode(bytes).replaceAll("\\s", "");

 }
}

Output:

Opened database successfully
CLAVE = 002
DATOS = ??????????

Operation done successfully
cipher: 
Byte: -123
String: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000


Decoded to be... 
Salida: BwoHCgcKBwoHCg==
Salida2: Dw8PDw8PDw8PDw==
Community
  • 1
  • 1
  • `new byte[0x85]` gives you an array of length 133, containing bytes that are all zeros. Also, you are not doing anything with the actual data you got from SQL. And that data is not a hex string, as you are getting `?????`. – RealSkeptic Oct 19 '16 at 08:17
  • the actual data I got from SQL is the string that I want to decrypt, see my attempts: String salida = new String(encode(data,shex)); String salida2 = new String(encode(data,keyStr)); Yes, that data is a string with value: áàöáà¥æêçêé – user6948899 Oct 19 '16 at 08:44
  • `key.getBytes()` uses the platform encoding to convert the characters to bytes. This is maybe UTF-8 in your case which would encode characters above 0x7F as more than one byte. I suggest you use the key in binary (byte[]). If you really have to represent it as string use Base64 encoding. – Henry Oct 19 '16 at 08:49
  • but if I declare data = "áàöáà¥æêçêé"; instead of got it from DB, the output is different. – user6948899 Oct 19 '16 at 08:50
  • Because the data from the database is *not* hexadecimal. It is *binary*, and it is encoded not in *ASCII*, which is only 0x00-0x7f, but in some other encoding, like ISO-8859-1. You should convert it to `String` by using the appropriate encoding. – RealSkeptic Oct 19 '16 at 08:51
  • How could I get the data as a binary? – user6948899 Oct 19 '16 at 10:46
  • Agreeing with @Henry, there is no point in saying "extended ASCII". When dealing with a character encoding, there is only that one—so, name it. (Or, say that it won't matter what the default is and that it can vary over time and machine.) – Tom Blodget Oct 19 '16 at 17:11

0 Answers0