Goal: Decode encrypted hex, which requires finding an unknown, single character key
I was purely trying to do the problem by XOR'ing each character in xOR with each of the ascii characters. I was expecting to get a String of hexes as one of my outputs. However, my catch statement says that every string it returns is not hex.
I then planned to take these converted hexvalues and just cast them as chars.
If you could offer me some guidance on how to fix this atrocity, it would be greatly appreicated.
Thanks a bunch!
//intention of this program is to decrypt this string of encoded hex, find the key, and decrpt the message
//however, its not really working. It doesnt print values prior to 112 even though those values arent blank
// as I checked in debugger
public static void main(String[] args) throws UnsupportedEncodingException
{
String xOr1 = ("1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736");
String xOr = "z({zzz{{z-{z{z{{{}z*{y)~x~x~{{rzsz(";
String result = "";
System.out.println("xOr1 length is " + xOr1.length());
String output = "";
byte[] encoded = xOr1.getBytes();
byte[] decoded;
String sub;
String matches = "(.*)abdef0123456789(.*)";
int hexInt;
for(int k = 0; k< 256;k++)
{
decoded = new byte[encoded.length];
result = "";
System.out.println(k);
for(int j = 0; j<encoded.length; j++)
{
decoded[j] = (byte)((int)encoded[j] ^ k);
result = Arrays.toString(decoded);
}
output = new String(decoded,"UTF-8");
//System.out.println(output);
try
{
for(int i = 0; i< output.length() -2; i++)
{
hexInt = Integer.parseInt(output,16);
System.out.println("You aren't dumb... " + output);
}
}
catch(NumberFormatException nfe)
{
//System.out.println(output);
System.out.println("bad boy");
}
}
}
Related
How to convert hex string to ansi (window 1252) and ansi (window 1252)to hex string in Java.
python (Works perfectly)
q = "hex string value"
x = bytes.fromhex(q).decode('ANSI')
a = x.encode("ANSI")
a = a.hex()
if q==a:
print("Correct")
Java (This code has a problem)
String hexOri = "hex string value";
StringBuilder output = new StringBuilder();
for (int i = 0; i < hexOri.length(); i+=2) {
String str = hexOri.substring(i, i+2);
output.append((char)Integer.parseInt(str, 16));
}
System.out.println("ANSI = " + output);
char [] chars = output.toString().toCharArray();
StringBuffer hexOutput = new StringBuffer();
for(int i = 0; i < chars.length; i++){
hexOutput.append(Integer.toHexString((int)chars[i]));
}
System.out.println("HexOutput = " + hexOutput.toString());
System.out.println(hexOri.equals(hexOutput.toString()));
Output from Python
Correct
Expected Output from Python
Correct
Output from Java
False
Expected Output from Java
Correct
In java the strings are encoded in UTF-16, so you can't read simply read/write the bytes of a string to get the encoding representation you desire.
You should use String#getBytes(String str, String charset) to get the string converted in the encoding you need and serialized to a byte array.
The same thing must be done to decode a byte array, using new String(buffer,encoding).
In both cases if you use the method without the charset it will use the default encoding for the JVM instance (which should be the system charset).
public static void main(String[] args) {
String str = "\tSome text [à]";
try {
System.out.println(str); // Some text [à]
String windowsLatin1 = "Cp1252";
String hexString = toHex(windowsLatin1, str);
System.out.println(hexString); // 09536f6d652074657874205be05d
String winString = toString(windowsLatin1, hexString);
System.out.println(winString); // Some text [à]
} catch (UnsupportedEncodingException e) {
// Should not happen.
}
}
public static String toString(String encoding, String hexString) throws UnsupportedEncodingException {
int length = hexString.length();
byte [] buffer = new byte[length/2];
for (int i = 0; i < length ; i+=2) {
String hexVal = hexString.substring(i,i+2);
byte code = (byte) Integer.parseInt(hexVal,16);
buffer[i/2]=code;
}
String winString = new String(buffer,encoding);
return winString;
}
public static String toHex(String encoding, String str) throws UnsupportedEncodingException {
byte[] bytes = str.getBytes(encoding);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
String hexChar = Integer.toHexString(b & 0xff);
if(hexChar.length()<2) {
builder.append('0');
}
builder.append(hexChar);
}
String hexString = builder.toString(); // 09536f6d652074657874205be05d
return hexString;
}
Java: I'm encrypting and decrypting a text file using a key of any two ASCII characters on the keyboard. I have them working correctly, except when I read the encrypted file to a string for decryption. It replaces some specific letter with a different incorrect letter, but not all of correct letters are replaced. Some t's are replaced with s's for example. I've also seen some b's be replaced with e's when I use a different key.
I've already looked through my encrypted/decryption algorithm. I copy and pasted the encrypted text file into my code and ran the algorithm again, it came out perfect. The only time the letters are replaced is when the encrypted algorithm is read from a text file to be decrypted.
public static String readFileToString(string filePath) {
StringBuilder builder = new StringBuilder();
try (Stream<String> stream = Files.get(filePath), StandardCharsets.UTF_8)){
stream.forEach(s->builder.append(s).append("\n");
}
catch(IOException e){
e.printStackTrace();
}
return builder.toString();
}
public static void writeFile(String crypt) throws IOException {
Scanner sc = new Scanner(System.in);
System.out.println("New file name: ");
String fileName = sc.nextLine();
String writtenString = crypt;
String userHome = System.getProperty("user.home");
File textFile = new File(userHome, fileName + ".txt");
BufferedWriter out = new BufferedWriter(new FileWriter(textFile));
out.write(writtenString);
out.close();
//Converts string and key into binary characters for 1-to-1 xOr to prevent any possible translation errors.
public static String crypt(String input, String key) throws UnsupportedEncodingException {
if (input.length() % 2 == 1) {
input = input + " ";
}
int n = input.length() / 2;
key = new String(new char[n]).replace("\0", key);
byte[] a = input.getBytes();
byte[] c = key.getBytes();
StringBuilder binaryBuilder = new StringBuilder();
StringBuilder binaryKeyBuilder = new StringBuilder();
//Creates a StringBuilder of bits using the file text
for(byte b: a) {
int value = b;
for(int i = 0; i < 8; i++) {
binaryBuilder.append((value & 128) == 0 ? 0 : 1);
value <<= 1;
}
binaryBuilder.append(' ');
}
//Converts binary StringBuilder to String
String binary = binaryBuilder.toString();
//Creates a StringBuilder of bits using the provided key
for(byte d: c) {
int keyValue = d;
for(int j = 0; j < 8; j++) {
binaryKeyBuilder.append((keyValue & 128) == 0 ? 0 : 1);
keyValue <<= 1;
}
binaryKeyBuilder.append(' ');
}
//Converts binaryKey StringBuilder to String
String binaryKey = binaryKeyBuilder.toString();
//Creates StringBuilder of bits using the provided key
StringBuilder xOr = new StringBuilder();
for(int q = 0; q < binary.length();q++) {
xOr.append(binary.charAt(q) ^ binaryKey.charAt(q));
}
String xOrResult = xOr.toString();
String cryptedString = "";
char next;
//Iterates through binary string to convert to ASCII characters 8 bits at a time.
for(int k = 0; k <= xOrResult.length()-8; k+=9) {
next = (char)Integer.parseInt(xOrResult.substring(k,k+8), 2);
cryptedString += next;
}
return cryptedString;
}
When I use the key "ty"
"Four score and seven years ago our fathers brought forth on this" is the correct phrasing.
However, I'm getting: "Four score and seven years ago our fashers broughs forth on this"
I would use binary file for encrypted text. It will save you from dealing with UTF-8 encoding/decoding some unusual code points. For example - when you xor 't' and 't' you get character with code 0.
You can also get unexpected new line characters. You actually replace all of them with '\n', but there are other options - '\r', or even two characters in sequence "\r\n". All of them will be replaced with '\n' in your code, and lead to mistakes after decryption.
What happened here:
Binary ASCII (or UTF-8) code for t is 01110100, and for y it is 01111001. When character y from key meets character t from text you get 01110100 xor 01111001 = 00001101 = 0x0D = '\r'. This character is written to file. When you read that file line by line, this '\r' is skipped as line separator. You replace it with '\n'=00001010 in line
stream.forEach(s->builder.append(s).append("\n");
When decrypting that text we get 00001010 (\n) xor 01111001 (y) = 01110011 (s).
I am trying to fill a byte array, 2 bytes at a time. My hw is a cryptography hw. I am to find the plain text from the given cipher text using a key. The key is 2 bytes long. The plain text was encrypted with many time pad. The Key is repeated until its as long as the plain text. I got the first 2 bytes of the key, now i just need to repeat it until its as long as the cipher text/plain text.
The cipher text length which is the same as the plain text length is 640138. The key is supposed to be this length as well, but what i got for key length after i applied the solution below was 640144. Doing Math.min below instead of Math.max gives an error String.checkBoundsBeginEnd.
I had to convert it to string because the builder is of type StringBuilder. "result" in this instance is key.
How do i make the key as long as the cipher text length?
byte[] cipherText = Files.readAllBytes(Paths.get("src/cipher3.bmp"));
byte[] plainText = new byte[cipherText.length];
byte[] pText = new byte[]{'B', 'M'};
byte[] key = new byte[pText.length];
for(int i = 0; i < pText.length; i++){
key[i] = (byte)(cipherText[i] ^ pText[i]);
}
String keyString = Arrays.toString(key);
System.out.println("The key " + keyString);
System.out.println("First two in ptext"+ Arrays.toString(pText));
System.out.println(plainText.length);
String plainlength = (String) Arrays.toString(new int[]{plainText.length});
System.out.println(plainlength);
StringBuilder builder = new StringBuilder(cipherText.length);
while(builder.length() < cipherText.length){
builder.append(keyString.substring(0, Math.max(keyString.length(), builder.length() -cipherText.length)));
}
String result = builder.toString();
System.out.println(result);
System.out.println(result.length());//this gives 640144
Math.min should be used to fill correctly. The
java.lang.StringIndexOutOfBoundsException: String index out of range: -640138
gives you clue on what is wrong. Negative input is applied on the subString method, obviously it must be Math.min(keyString.length(), builder.length() -cipherText.length. Since cipherText length must greater than or equals to builder length, you should swap the arguments to give correct result.
public class Fill2ByteToArray {
public static void main(String[] args) throws IOException {
int targetLength = 640138;
byte[] cipherText = new byte[targetLength];
for (int i = 0; i < cipherText.length; i++) {
cipherText[i] = Integer.valueOf(i).byteValue();
}
byte[] plainText = new byte[cipherText.length];
byte[] pText = new byte[] { 'B', 'M' };
byte[] key = new byte[pText.length];
for (int i = 0; i < pText.length; i++) {
key[i] = (byte) (cipherText[i] ^ pText[i]);
}
String keyString = Arrays.toString(key);
System.out.println("The key " + keyString);
System.out.println("First two in ptext" + Arrays.toString(pText));
System.out.println(plainText.length);
String plainlength = (String) Arrays.toString(new int[] { plainText.length });
System.out.println(plainlength);
StringBuilder builder = new StringBuilder(cipherText.length);
while (builder.length() < cipherText.length) {
builder.append(keyString.substring(0, Math.min(keyString.length(), cipherText.length-builder.length())));
}
String result = builder.toString();
System.out.println(result);
System.out.println(result.length());
}
}
I have converted regional language word to hex value and saved to DB. But How can i decode that hexa value back to regional language word.
Here is my Kannada/Telugu word to Hex value conversion
public String toHex(String b){
String s="";
for (int i=0; i<b.length(); ++i) s+=String.format("%04X",b.charAt(i)&0xffff);
System.out.println("Converted value:::"+s); //0C1C0C3E0C350C3E
return s;
}
Word i have saved is జావా
Hex value saved in database is 0C1C0C3E0C350C3E
Decoded output am getting is : >5>
Is there any way to decode the hex value back to జావా
Code used to decode is
byte[] bytes = DatatypeConverter.parseHexBinary(itemName);
String s= new String(bytes, "UTF-8");
System.out.println("Utf..."+s);
Please help...
public String fromHex(String b) {
char[] cs = new char[b.length() / 4];
for (int i = 0; i < cs.length; ++i) {
int c = Integer.parseInt(b.substring(4 * i, 4 * i + 4), 16) & 0xFFFF;
cs[i] = (char) c;
}
return new String(cs);
}
This assumes that the conversion did not meddle with negative hex values.
Or exploiting that char is UTF-16BE:
byte[] bytes = DatatypeConverter.parseHexBinary(itemName);
return new String(bytes, StandardCharsets.UTF_16);
char[] data = hexData.toCharArray();
byte[] bytes = new byte[data.length/2];
for (int i = 0; i < data.length; i += 2) {
String val = new String(data, i, 2);
bytes[i/2] = Integer.valueOf(val, 16).byteValue();
}
String text = new String(bytes, "UTF8");
You might add sanity checks, e.g. that the length of the input-array is even, etc.
Need to decode hex code in array when accessed by index.User should enter array index and get decoded hex in array as output.
import java.util.Scanner;
class Find {
static String[] data={ " \\x6C\\x65\\x6E\\x67\\x74\\x68",
"\\x73\\x68\\x69\\x66\\x74"
//....etc upto 850 index
};
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Enter a number");
int s = in.nextInt();
String decodeinput=data[s];
// need to add some code here
//to decode hex and store to a string decodeoutput to print it
String decodeoutput=......
System.out.println();
}
}
How about using...
String hexString ="some hex string";
byte[] bytes = Hex.decodeHex(hexString .toCharArray());
System.out.println(new String(bytes, "UTF-8"));
Append the following code after getting the value of s from user. Imp: Please use camelCase convention for naming variables as pointed out above. I have just gone ahead and used the same names as you have for your convinience for now.
if (s>= 0 && s < data.length) {
String decodeinput = data[s].trim();
StringBuilder decodeoutput = new StringBuilder();
for (int i = 2; i < decodeinput.length() - 1; i += 4) {
// Extract the hex values in pairs
String temp = decodeinput.substring(i, (i + 2));
// convert hex to decimal equivalent and then convert it to character
decodeoutput.append((char) Integer.parseInt(temp, 16));
}
System.out.println("ASCII equivalent : " + decodeoutput.toString());
}
OR, just complete what you were doing:
/* import java.io.UnsupportedEncodingException;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex; //present in commons-codec-1.7.jar
*/
if (s>= 0 && s < data.length) {
String hexString =data[s].trim();
hexString = hexString.replace("\\x", "");
byte[] bytes;
try {
bytes = Hex.decodeHex(hexString.toCharArray());
System.out.println("ASCII equivalent : " + new String(bytes, "UTF-8"));
} catch (DecoderException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}