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());
}
}
Related
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 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.
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");
}
}
}
Hi Team,Firstly I don't want a byte[] array made from the actual String/char[]
//NO!
String s = "abc";
byte[] bytes = s.getBytes();
I want a byte[] array constructed by the contents and representation of the String, like so.
byte[] b = "new byte[]{1,2,3}"
//Again I don't want >> byte[] b = new String("new byte[]{1,2,3}").getBytes();
thanks Team.
This worked for me -
/**
* Parse a properly formatted String into a byte array.
*
* #param in
* The string to parse - must be formatted
* "new byte[]{1,2,n}"
* #return The byte array parsed from the input string.
*/
public static byte[] parseByteArrayFromString(
String in) {
in = (in != null) ? in.trim() : "";
// Opening stanza.
if (in.startsWith("new byte[]{")) {
// Correct closing brace?
if (in.endsWith("}")) {
// substring the input.
in = in.substring(11, in.length() - 1);
// Create a list of Byte(s).
List<Byte> al = new ArrayList<Byte>();
// Tokenize the input.
StringTokenizer st = new StringTokenizer(in,
",");
while (st.hasMoreTokens()) {
String token = st.nextToken();
// Add a Byte.
al.add(Byte.valueOf(token.trim()));
}
// Convert from the List to an Array.
byte[] ret = new byte[al.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = al.get(i);
}
return ret;
}
}
return new byte[] {};
}
public static void main(String[] args) {
byte[] vals = parseByteArrayFromString("new byte[]{1,2,3}");
System.out.println(Arrays.toString(vals));
}
Well, you could always just traverse through the array and put those values in a string, then put those in a byte array.
String d = "new byte[]{";
for(int i = 0; i < s.length() - 1; i++)
d += s.charAt(i) +",";
d += s.charAt(s.length() - 1) + "}";
byte[] b = d.getBytes();
You can extract bytes by using regular expression, such as:
Pattern pattern = Pattern.compile("(\\d+)");
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
Byte.parseByte(matcher.group(0)).byteValue(); // Use this
}
In the while loop, use can add them to an array to use it later or print it to console, or any else. It's up to you.
For sure that input string is correct, add another pattern to check that string if necessary. For example:
Pattern.compile("new byte\\[\\] ?\\{((\\d+),? *)+\\}");
String str = "9B7D2C34A366BF890C730641E6CECF6F";
I want to convert str into byte array, but str.getBytes() returns 32 bytes instead of 16.
I think what the questioner is after is converting the string representation of a hexadecimal value to a byte array representing that hexadecimal value.
The apache commons-codec has a class for that, Hex.
String s = "9B7D2C34A366BF890C730641E6CECF6F";
byte[] bytes = Hex.decodeHex(s.toCharArray());
Java SE 6 or Java EE 5 provides a method to do this now so there is no need for extra libraries.
The method is DatatypeConverter.parseHexBinary
In this case it can be used as follows:
String str = "9B7D2C34A366BF890C730641E6CECF6F";
byte[] bytes = DatatypeConverter.parseHexBinary(str);
The class also provides type conversions for many other formats that are generally used in XML.
Use:
str.getBytes("UTF-16LE");
I know it's late but hope it will help someone else...
This is my code: It takes two by two hex representations contained in String and add those into byte array.
It works perfectly for me.
public byte[] stringToByteArray (String s) {
byte[] byteArray = new byte[s.length()/2];
String[] strBytes = new String[s.length()/2];
int k = 0;
for (int i = 0; i < s.length(); i=i+2) {
int j = i+2;
strBytes[k] = s.substring(i,j);
byteArray[k] = (byte)Integer.parseInt(strBytes[k], 16);
k++;
}
return byteArray;
}
That should do the trick :
byte[] bytes = toByteArray(Str.toCharArray());
public static byte[] toByteArray(char[] array) {
return toByteArray(array, Charset.defaultCharset());
}
public static byte[] toByteArray(char[] array, Charset charset) {
CharBuffer cbuf = CharBuffer.wrap(array);
ByteBuffer bbuf = charset.encode(cbuf);
return bbuf.array();
}
try this:
String str = "9B7D2C34A366BF890C730641E6CECF6F";
String[] temp = str.split(",");
bytesArray = new byte[temp.length];
int index = 0;
for (String item: temp) {
bytesArray[index] = Byte.parseByte(item);
index++;
}
I assume what you need is to convert a hex string into a byte array that equals that means the same thing as that hex string?
Adding this method should do it for you, without any extra library importing:
public static byte[] hexToByteArray(String s) {
String[] strBytes = s.split("(?<=\\G.{2})");
byte[] bytes = new byte[strBytes.length];
for(int i = 0; i < strBytes.length; i++)
bytes[i] = (byte)Integer.parseInt(strBytes[i], 16);
return bytes;
}