Combine int & byte into long - java

I have two numbers: one is an int, other is byte. I want to create a single long value out of them in a way that person knowing the byte value can decipher original int from it. Whats the best way to do it?

Assuming i understood your question correct,
The Simplest Solution, You Could XOR the 'int' using the 'byte'
Repeat the process to decrypt...
byte key = 8;
int secret = 123;
System.out.println("Secret : " + secret);
int encrypted = (secret ^ (key | (key << 8)));
System.out.println("Encrypted : " + encrypted );
int decrypt = (encrypted ^ (key | (key << 8)));
System.out.println("Decrypted : " + decrypt );
The result is an 'int' but, you could always just cast it into a long...

long mylong = (((long)mybyte) << 40) | myint;
To retrieve the original value:
int myorigint = (int)(mylong & ~(((long)mybyte) << 40));
But this requires 8-byte longs. Which are not required by the C standard. If a long is 4 bytes, you're out of luck. This means long and int would have the same length. If sizeof(int)==sizeof(long)==4, then asking to store an int and a byte in a long is asking to store 5 arbitrary bytes of information in 4 bytes. Which is completely impossible.
Of course, there's also the trivial "solution":
long mylong = (long)myint;
and the reverse is:
int myint = (int)mylong;
Now, someone knowing (or not knowing!) the byte can retrieve the original data.
If you want a solution such that only someone knowing the correct byte can retrieve the original int, you can use this:
long mylong = (long)(myint-mybyte);
and reverse:
int myint = (int)(mylong+mybyte);
But know that encrypting four bytes with one byte will not be truly secure. You should use a 4-byte one-time pad to encrypt four bytes. If you have a four-byte key, use XOR for a truly unbreakable cipher. No, really.

One idea is to apply a reversible function the number of times indicated by the byte.
To get the original number back just apply the inverse function the same number of times.
e.g.
public static int encrypt(int value, byte key) {
int result=value;
for (int i=0; i<=(key&255); i++) {
result=Integer.rotateRight(result,7)^(i+0xCAFEBABE);
}
return result;
}
Finding the reverse function left as an exercise for the reader.....

Related

Caesar in CBC / How to XOR in Java?

I have been trying out to ''improve'' the simple Caesar encryption by encrypting in the CBC mode.
As I understand, the first character has to be XORed by an initialization vector and then by the key, the output then is the first character of the encrypted text. This will then be XORed by the second char, then again XORed by the key, … and so forth.
I don't quite understand how the XORing should work.
Let us have the translation table given (only space and A-Z):
/s: 0, A: 1, B: 2, …, Z: 26,
key: 1,
Init.vector: 5
Using the simple Caesar, ''HELLO'' -> {8,5,12,12,20} -> {9,6,13,13,21} -> ''IFMMP''
But how would I get to encrypt using CBC?
It'd be especially helpful if you could show me how to implement it in Java. Thanks!
Hmm I interpret your question like you think you want to xor by the key to your cipher, this is wrong:
You xor by the previous result from the cipher. Something like this:
// Untested code
// The code below need to be adjusted for it to print meaningful
// characters in the encrypted string as the xor function produces
// integers outside the range of standard ascii characters
private void cbcCaesar(){
int key = 1;
String message = "java";
int initialisationVector = 5; // the IV is not super necessarily hidden from an attacker but should be different for each message
StringBuilder encryptedMessageBuilder = new StringBuilder();
char[] charArray = message.toCharArray();
int encryptedLetter = initialisationVector;
for (int letter : charArray){
int xorApplied = letter ^ encryptedLetter;
encryptedLetter = applyCaesarCipher(xorApplied, key);
encryptedMessageBuilder.append((char) encryptedLetter);
}
System.out.println(encryptedMessageBuilder.toString());
}
private int applyCaesarCipher(int xorApplied, int key) {
return (xorApplied+ key) % 26;
}
The easiest way to convert the above snippet to something usable would be to map letters to the numbers 0-26 and use that instead of the char's ascii encoding
I found this resource to be pretty good https://www.youtube.com/watch?v=0D7OwYp6ZEc

Java integer to hex and to int

I have the problem, that the method does not work as expected. In most cases it works. However there is a case it does not work.
I have a byte array containing some values. In hex e.g.: 0x04 0x42 (littleEndian). If I use the method convertTwoBytesToInt, I get a really small number. It should be > 16000 and not smaller than 2000.
I have two methods:
private static int convertTwoBytesToInt(byte[] a){
String f1 = convertByteToHex(a[0]);
String f2 = convertByteToHex(a[1]);
return Integer.parseInt(f2+f1,RADIX16);
}
private static byte[] convertIntToTwoByte(int value){
byte[] bytes = ByteBuffer.allocate(4).putInt(value).array();
System.out.println("Check: "+Arrays.toString(bytes));
byte[] result = new byte[2];
//big to little endian:
result[0] = bytes[3];
result[1] = bytes[2];
return result;
}
I call them as follows:
byte[] h = convertIntToTwoByte(16000);
System.out.println("AtS: "+Arrays.toString(h));
System.out.println("tBtInt: "+convertTwoBytesToInt(h));
If I use the value 16000, there is no problem, but if I use 16900, the integer value of "convertTwoBytesToInt" is 1060.
Any Idea?
Based on the example you provided, my guess is that convertByteToHex(byte) is converting to a single-digit hex string when the byte value is less than 0x10. 16900 is 0x4204 and 1060 is 0x424.
You need to ensure that the conversion is zero-padded to two digits.
A much simpler approach is to use bit manipulation to construct the int value from the bytes:
private static int convertTwoBytesToInt(byte[] a) {
return ((a[1] & 0xff) << 8) | (a[0] & 0xff);
}

What is the purpose to add padding to hex?

Hi I read this post on how to implement salt and hashing to the password and I am stuck on specified code underneath the website I specified above.
private static String toHex(byte[] array)
{
BigInteger bi = new BigInteger(1, array);
String hex = bi.toString(16);
int paddingLength = (array.length * 2) - hex.length();
if(paddingLength > 0)
return String.format("%0" + paddingLength + "d", 0) + hex;
else
return hex;
}
My question is that why did they calculate the paddingLength and implement it to the hex if the result paddingLength is greater than zero?
BigInteger(byte[]) interprets the byte array into a two's complement value; this means that it has 2^(8*N) possible values for an N-length array (since each byte contains 8 bits).
Meanwhile, a hex string of length M has 16^M possible values (since each character encodes one of 16 values).
The authors want a one-to-one mapping between the byte[] and the String: given a String, you should be able to exactly determine the byte[] it came from. To get that, we have to make sure the string can encode exactly as many values as the byte[]. Plugging in the numbers from above, we get:
(# values for an N-length byte[]) == (# values for an M-length String)
2^(8*N) == 16^M
Let's solve for M in terms of N. The first step is to re-write that right-hand side. If you remember your exponent power rules, a^(b*c) == (a^b)^c. Let's get the base of the exponent on the right to be a 2:
== (2^4)^M
== 2^(4*M)
So we have 2^(8*N) == 2^(4*M). If 2^k == 2^j, that means k == j. So, 8*N == 4*M. Dividing both sides by 4 yields M = 2N.
To tie it back together, remember that N was the length of the byte array, and M was the length of the hex string. We've just figured out that for there to be a one-to-one mapping, M = 2N -- in other words, the hex string should be twice as long as the byte array.
The padding ensures that.
Because they wanted all the bytes in the array to be represented in the hex string, even if they are leading zero bytes.
It is not the most obvious way to write a toHex method though.
I find something like this much clearer:
private static String toHex(byte[] array) {
StringBuilder s = new StringBuilder();
for (byte b : array) {
s.append(String.format("%02x", b));
}
return s.toString();
}

Converting String type binary number to bit in java

I have a question about converting String type binary number to bit and write in the txt file.
For example we have String like "0101011" and want to convert to bit type "0101011"
then write in to the file on the disk.
I would like to know is there anyway to covert to string to bit..
i was searching on the web they suggest to use bitarray but i am not sure
thanks
Try this:
int value = Integer.parseInt("0101011", 2); // parse base 2
Then the bit pattern in value will correspond to the binary interpretation of the string "0101011". You can then write value out to a file as a byte (assuming the string is no more than 8 binary digits).
EDIT You could also use Byte.parseByte("0101011", 2);. However, byte values in Java are always signed. If you tried to parse an 8-bit value with the 8th bit set (like "10010110", which is 150 decimal), you would get a NumberFormatException because values above +127 do not fit in a byte. If you don't need to handle bit patterns greater than "01111111", then Byte.parseByte works just as well as Integer.parseInt.
Recall, though, that to write a byte to a file, you use OutputStream.write(int), which takes an int (not byte) value—even though it only writes one byte. Might as well go with an int value to start with.
You can try the below code to avoid overflows of the numbers.
long avoidOverflows = Long.parseLong("11000000000000000000000000000000", 2);
int thisShouldBeANegativeNumber = (int) avoidOverflows;
System.out.println("Currect value : " + avoidOverflows + " -> " + "Int value : " + thisShouldBeANegativeNumber);
you can see the output
Currect value : 3221225472 -> Int value : -1073741824
//Converting String to Bytes
bytes[] cipherText= new String("0101011").getBytes()
//Converting bytes to Bits and Convert to String
StringBuilder sb = new StringBuilder(cipherText.length * Byte.SIZE);
for( int i = 0; i < Byte.SIZE * cipherText .length; i++ )
sb.append((cipherText [i / Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1');
//Byte code of input in Stirn form
System.out.println("Bytecode="+sb.toString()); // some binary data
//Convert Byte To characters
String bin = sb.toString();
StringBuilder b = new StringBuilder();
int len = bin.length();
int i = 0;
while (i + 8 <= len) {
char c = convert(bin.substring(i, i+8));
i+=8;
b.append(c);
}
//String format of Binary data
System.out.println(b.toString());

Java converting int to hex and back again

I have the following code...
int Val=-32768;
String Hex=Integer.toHexString(Val);
This equates to ffff8000
int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int"
So, initially, it converts the value -32768 into a hex string ffff8000, but then it can't convert the hex string back into an Integer.
In .Net it works as I'd expect, and returns -32768.
I know that I could write my own little method to convert this myself, but I'm just wondering if I'm missing something, or if this is genuinely a bug?
int val = -32768;
String hex = Integer.toHexString(val);
int parsedResult = (int) Long.parseLong(hex, 16);
System.out.println(parsedResult);
That's how you can do it.
The reason why it doesn't work your way: Integer.parseInt takes a signed int, while toHexString produces an unsigned result. So if you insert something higher than 0x7FFFFFF, an error will be thrown automatically. If you parse it as long instead, it will still be signed. But when you cast it back to int, it will overflow to the correct value.
It overflows, because the number is negative.
Try this and it will work:
int n = (int) Long.parseLong("ffff8000", 16);
int to Hex :
Integer.toHexString(intValue);
Hex to int :
Integer.valueOf(hexString, 16).intValue();
You may also want to use long instead of int (if the value does not fit the int bounds):
Hex to long:
Long.valueOf(hexString, 16).longValue()
long to Hex
Long.toHexString(longValue)
It's worth mentioning that Java 8 has the methods Integer.parseUnsignedInt and Long.parseUnsignedLong that does what you wanted, specifically:
Integer.parseUnsignedInt("ffff8000",16) == -32768
The name is a bit confusing, as it parses a signed integer from a hex string, but it does the work.
Try using BigInteger class, it works.
int Val=-32768;
String Hex=Integer.toHexString(Val);
//int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
//int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int"
BigInteger i = new BigInteger(Hex,16);
System.out.println(i.intValue());
As Integer.toHexString(byte/integer) is not working when you are trying to convert signed bytes like UTF-16 decoded characters you have to use:
Integer.toString(byte/integer, 16);
or
String.format("%02X", byte/integer);
reverse you can use
Integer.parseInt(hexString, 16);
Java's parseInt method is actally a bunch of code eating "false" hex : if you want to translate -32768, you should convert the absolute value into hex, then prepend the string with '-'.
There is a sample of Integer.java file :
public static int parseInt(String s, int radix)
The description is quite explicit :
* Parses the string argument as a signed integer in the radix
* specified by the second argument. The characters in the string
...
...
* parseInt("0", 10) returns 0
* parseInt("473", 10) returns 473
* parseInt("-0", 10) returns 0
* parseInt("-FF", 16) returns -255
Using Integer.toHexString(...) is a good answer. But personally prefer to use String.format(...).
Try this sample as a test.
byte[] values = new byte[64];
Arrays.fill(values, (byte)8); //Fills array with 8 just for test
String valuesStr = "";
for(int i = 0; i < values.length; i++)
valuesStr += String.format("0x%02x", values[i] & 0xff) + " ";
valuesStr.trim();
Below code would work:
int a=-32768;
String a1=Integer.toHexString(a);
int parsedResult=(int)Long.parseLong(a1,16);
System.out.println("Parsed Value is " +parsedResult);
Hehe, curious. I think this is an "intentianal bug", so to speak.
The underlying reason is how the Integer class is written. Basically, parseInt is "optimized" for positive numbers. When it parses the string, it builds the result cumulatively, but negated. Then it flips the sign of the end-result.
Example:
66 = 0x42
parsed like:
4*(-1) = -4
-4 * 16 = -64 (hex 4 parsed)
-64 - 2 = -66 (hex 2 parsed)
return -66 * (-1) = 66
Now, let's look at your example
FFFF8000
16*(-1) = -16 (first F parsed)
-16*16 = -256
-256 - 16 = -272 (second F parsed)
-272 * 16 = -4352
-4352 - 16 = -4368 (third F parsed)
-4352 * 16 = -69888
-69888 - 16 = -69904 (forth F parsed)
-69904 * 16 = -1118464
-1118464 - 8 = -1118472 (8 parsed)
-1118464 * 16 = -17895552
-17895552 - 0 = -17895552 (first 0 parsed)
Here it blows up since -17895552 < -Integer.MAX_VALUE / 16 (-134217728).
Attempting to execute the next logical step in the chain (-17895552 * 16)
would cause an integer overflow error.
Edit (addition): in order for the parseInt() to work "consistently" for -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, they would have had to implement logic to "rotate" when reaching -Integer.MAX_VALUE in the cumulative result, starting over at the max-end of the integer range and continuing downwards from there. Why they did not do this, one would have to ask Josh Bloch or whoever implemented it in the first place. It might just be an optimization.
However,
Hex=Integer.toHexString(Integer.MAX_VALUE);
System.out.println(Hex);
System.out.println(Integer.parseInt(Hex.toUpperCase(), 16));
works just fine, for just this reason. In the sourcee for Integer you can find this comment.
// Accumulating negatively avoids surprises near MAX_VALUE

Categories