Using java to encrypt integers - java

I'm trying to encrypt some integers in java using java.security and javax.crypto.
The problem seems to be that the Cipher class only encrypts byte arrays. I can't directly convert an integer to a byte string (or can I?). What is the best way to do this?
Should I convert the integer to a string and the string to byte[]? This seems too inefficient.
Does anyone know a quick/easy or efficient way to do it?
Please let me know.
Thanks in advance.
jbu

You can turn ints into a byte[] using a DataOutputStream, like this:
ByteArrayOutputStream baos = new ByteArrayOutputStream ();
DataOutputStream dos = new DataOutputStream (baos);
dos.writeInt (i);
byte[] data = baos.toByteArray();
// do encryption
Then to decrypt it later:
byte[] decrypted = decrypt (data);
ByteArrayInputStream bais = new ByteArrayInputStream (data);
DataInputStream dis = new DataInputStream (bais);
int j = dis.readInt();

You can also use BigInteger for conversion:
BigInteger.valueOf(integer).toByteArray();

Just use NIO. It's designed for this specific purpose. ByteBuffer and IntBuffer will do what you need quickly, efficiently, and elegantly. It'll handle big/little endian conversion, "direct" buffers for high performance IO, and you can even mix data types into the byte buffer.
Convert integers into bytes:
ByteBuffer bbuffer = ByteBuffer.allocate(4*theIntArray.length);
IntBuffer ibuffer = bbuffer.asIntBuffer(); //wrapper--doesn't allocate more memory
ibuffer.put(theIntArray); //add your int's here; can use
//array if you want
byte[] rawBytes = bbuffer.array(); //returns array backed by bbuffer--
//i.e. *doesn't* allocate more memory
Convert bytes into integers:
ByteBuffer bbuffer = ByteBuffer.wrap(rawBytes);
IntBuffer ibuffer = bbuffer.asIntBuffer();
while(ibuffer.hasRemaining())
System.out.println(ibuffer.get()); //also has bulk operators

I have found the following code that may help you, since Integer in Java is always 4 bytes long.
public static byte[] intToFourBytes(int i, boolean bigEndian) {
if (bigEndian) {
byte[] data = new byte[4];
data[3] = (byte) (i & 0xFF);
data[2] = (byte) ((i >> 8) & 0xFF);
data[1] = (byte) ((i >> 16) & 0xFF);
data[0] = (byte) ((i >> 24) & 0xFF);
return data;
} else {
byte[] data = new byte[4];
data[0] = (byte) (i & 0xFF);
data[1] = (byte) ((i >> 8) & 0xFF);
data[2] = (byte) ((i >> 16) & 0xFF);
data[3] = (byte) ((i >> 24) & 0xFF);
return data;
}
}
You can find more information about the bigEndian parameter here:
http://en.wikipedia.org/wiki/Endianness

create a 4-byte array and copy the int to the array in 4 steps, with bitwise ANDs and bitshifting, like Paulo said.
But remember that block algorithms such as AES and DES work with 8 or 16 byte blocks so you will need to pad the array to what the algorithm needs. Maybe leave the first 4 bytes of an 8-byte array as 0's, and the other 4 bytes contain the integer.

Just use:
Integer.toString(int).getBytes();
Make sure you use your original int and getBytes() will return a byte array. No need to do anything else complicated.
To convert back:
Integer.parseInt(encryptedString);

My Simple Solution is that Encrypt Integer to the String by shifting ASCII Value of the Integer by the secret key you Provide.
Here is the Solution:
public String encodeDiscussionId(int Id) {
String tempEn = Id + "";
String encryptNum ="";
for(int i=0;i<tempEn.length();i++) {
int a = (int)tempEn.charAt(i);
a+=148113;
encryptNum +=(char)a;
}
return encryptNum;
}
public Integer decodeDiscussionId(String encryptText) {
String decodeText = "";
for(int i=0;i<encryptText.length();i++) {
int a= (int)encryptText.charAt(i);
a -= 148113;
decodeText +=(char)a;
}
int decodeId = Integer.parseInt(decodeText);
return decodeId;
}
Steps to Encode:
Here, First you convert the Given Integer into String by: String temp = givenInt + ""
Scan each character of String, Read ASCII of that character and add it with secret key as 148113 in this case.
Convert shifted Integer into Character and concatenate to the String encryptNum and finally return it.
Steps to Decode:
Scan each character of String, Read ASCII of that character and subtract it with secret key as previous.
Convert that value to character and concatenate with decodeText.
As previous encode output is always String '???' and vary according to number of digits of input Id.

Related

How to create byte[] from hexadecimal values?

I have the following values:
public static short TAG_VALUE1 = 0x2E09;
public static short TAG_VALUE2 = 0x2E0D;
And I want to create a byte[] from both values. As a byte array, I have to get the first byte and insert it into the array and then the second byte of each TAG. I tried to convert to string and then go back, but I think it has to be an easier way to do so.
How can I get this in a byte[] that looks like this?
2E 09 2E 0D
How about
byte[] foo = new byte[] {
(byte) (TAG_VALUE1>>8),
(byte) (TAG_VALUE1),
(byte) (TAG_VALUE2>>8),
(byte) (TAG_VALUE2),
};
See ByteBuffer and its many uses.
byte[] bytes = new byte[4];
ByteBuffer buf = ByteBuffer.wrap(bytes);
buf.putShort(TAG_VALUE1);
buf.putShort(TAG_VALUE2);

Conversion python to Java

I need to convert this Python code in Java but the '\x00' hexcode is a real problem.
How can I do the export data to bytes[] ?
message__FirstPart = '\x45\x55\x43\x45\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00'
# event_par = key number (5+ 0..9
message__event_par = chr(key+5)
message__filler = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
# mit link state = 1
message__link_status = chr(int(GroupID))
# mit link state = 1
#message__link_status = '\x01'
# the sender’s mac-address
message__mac = '\x00\x00\x00\x00\x00\x00'
data = message__FirstPart + message__event_par + message__filler + message__link_status + message__mac
Thanks !
Strings in Java are made up of char, not byte. Though a char is really just two bytes, it is interpreted as UTF-16 and this can cause all sorts of trouble when you really want to talk about a series of bytes as it appears in your example.
You can express literal bytes as hexadecimal in Java as 0x00, 0x01, ..., 0xFF though these usually get interpreted as int and must be cast to byte:
byte[] arr = new byte[] { (byte) 0x01, (byte) 0x02 };
You can also look into the ByteBuffer class for assembling streams of bytes.

Converts bytes into a string in Decimal - Translate code .NET to Java

I have to "convert" the following .NET code to JAVA :
StringBuilder result = new StringBuilder();
foreach (byte current in hashBytes)
{
result.Append(current.ToString("D").PadLeft(numberOfCharactersInStringRepresentationForByte, '0'));
}
return result.ToString();
I have a hashBytes the byte[] to convert
and
numberOfCharactersInStringRepresentationForByte = 3
How can i do it?
Thanks.
So far i got :
StringBuilder result = new StringBuilder();
for (byte current : hashBytes)
{
int currentUnsigned = (int) current & 0xFF; //Convert the signed byte to unsigned
String currentUnsignedWithPadding = String.format("%3s", currentUnsigned).replace(' ', '0'); //Add tha "0" padding. AABBCCC will be 0AA0BBCCC
result.append(currentUnsignedWithPadding);
}
System.out.println(result.toString());
It seem's to work.
Please let me know if there are some more elegant/optimized ways to do the same.

convert string with hexa to byte

I've a String with value 0xE20x800x93.
I try to convert them like this and it works
byte[] bs = new byte[]{
(byte) 0xE2,(byte) 0x80, (byte) 0x93
};
But what I want is without doing the explicit casting, I need to convert it into a byte array.
Or at least a way to convert into a byte object, and not a byte[] object.
You can do it in one (albeit long) line:
byte[] bytes = Arrays.copyOfRange(new ByteBuffer().putInt(Integer.parseInt(str.replace("0x", ""), 16)).array(), 1, 4);
This assumes you have exactly 3 bytes to get. If it's a variable length, the following code is more generic, but slightly more verbose, because it uses the length of the input to determine the eventual result size:
byte[] bytes = Arrays.copyOfRange(new ByteBuffer().putInt(Integer.parseInt(str.replace("0x", ""), 16)).array(), 4 - str.length() / 4, 4);
try DatatypeConverter.parseHexBinary(str) from javax.xml.bind package

Java ME MD5 string using bouncy castle - cannot hash multiple times

I've noticed that a lot of my Google searches took me here so i thought perhaps i could borrow your apt minds :)
I'm working on a One Time Password generator for a mobile device (as well as website to log in to) as part of my third year degree dissertation.
Using the org.bouncycastle.crypto.digests.MD5Digest library i am taking a byte array (from a string user input) then hashing it X number of times. This is also known as daisy chaining hash strings or lamports method of encryption.
My issue is that if the string is hashed once then it correctly hashes it, however if the new hash is hashed again the outcome is incorrect.
See code below:
private String generateHash(String OTP, int loopNum)
{
byte[] secretBytes = OTP.getBytes();
for (int x = 0; x < loopNum; x++)
{
byte[] tempStore = new byte[16];
tempStore = hash(secretBytes);
secretBytes = tempStore;
}
return convertToHex(secretBytes);
}
public byte[] hash(byte[] secretBytes)
{
org.bouncycastle.crypto.digests.MD5Digest digest = new org.bouncycastle.crypto.digests.MD5Digest();
digest.reset();
// Update MD5 digest with user secret in byte format
digest.update(secretBytes, 0, secretBytes.length);
// get length of digest to initialise new md5 byte array
int length = digest.getDigestSize();
// create md5 byte array using length
byte[] md5 = new byte[length];
// calculate MD5 hash, using md5 byte array, 0 for buffer offset
digest.doFinal(md5, 0);
return md5;
}
private static String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
String Hex;
String formattedHex;
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] <<< 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a'+ (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
Hex = buf.toString();
formattedHex = "\n" + Hex.substring(0, 4) + " " + Hex.substring(4, 8) + " " + Hex.substring(8, 12) + " "
+ Hex.substring(12, 16) + " " + Hex.substring(16, 20) + " " +Hex.substring(20, 24) + " "
+ Hex.substring(24, 28) + " " + Hex.substring(28, 32);
return formattedHex;
}
I think it is either;
The digest does not return a correct byte array
The Hex converter incorrectly converts this
Im testing using the secret of: A
which has the following MD5 Outputs:
7fc56270e7a70fa81a5935b72eacbe29
8f28f2e7231860115d2a8cacba019dbe (this should be 4cbd6d53280de25e04712c7434a70642)
Many thanks for your help in advance :)
p.s. I'm checking it against a PHP md5 could this also be an issue?
MD5, when applied to an input consisting in a single byte of value 0x41 (an 'A'), yields a 16-byte output which, when printed in hexadecimal, is 7fc56270e7a70fa81a5935b72eacbe29.
If you apply MD5 on those 16 bytes, you should get 8f28f2e7231860115d2a8cacba019dbe, and that's what you get.
Now, if you consider MD5 applied on a 32-byte string which is the ASCII encoding of the character string "7fc56270e7a70fa81a5935b72eacbe29", then this yields 4cbd6d53280de25e04712c7434a70642. So I think that your Java code is fine (for that) and that your confusion comes from how you give the input data to your PHP-based test code. You write 7fc562... and you think about it as "one byte of value 0x7f, then one byte of value 0xc5, then..." but the PHP code takes it as "one byte of value 0x37 (ASCII code for a '7'), then one byte of value 0x66 (ASCII code for an 'f'), then...".
On a Linux system, try this:
$ printf A | md5sum
7fc56270e7a70fa81a5935b72eacbe29 -
$ printf 7fc56270e7a70fa81a5935b72eacbe29 | md5sum
4cbd6d53280de25e04712c7434a70642 -
$ printf "\x7f\xc5\x62\x70\xe7\xa7\x0f\xa8\x1a\x59\x35\xb7\x2e\xac\xbe\x29" | md5sum
8f28f2e7231860115d2a8cacba019dbe -
As side notes:
Be wary of OTP.getBytes(). It converts a string into bytes by using the locale-dependent charset. This will use UTF-8, UTF-16, ISO-8859-1,... depending on the system configuration, usually tied to the "system language". Your code will act differently on the same string, which is rarely a good idea. Instead, use OTP.getBytes("UTF-8") which will compute the same bytes regardless of the local configuration.
Your hash loop includes useless mantras. For instance, you allocate a 16-byte array, which you never use.
It is considered bad coding-style in Java to have a variable name beginning with an uppercase letter. If you plan on showing your code in a school context then you should rename Hex into hex.
When halfByte is obtained as the result of a "& 0x0F" then it necessarily contains a value between 0 and 15. The "0 <= halfByte" test is unnecessary.
Thank you all very much for your help, the problem was that my java md5 did not behave like a php MD5.
I found a solution to the problem which basically (in Java) take the byte array and convert it into a hex string and THEN get the bytes for this string which is then MD5'd rather than using the un hex'd byte array. See solutions below
See the following for the result: http://forums.sun.com/thread.jspa?forumID=9&threadID=718781
static String byteArrayToHexString(byte byteValues[]) {
byte singleChar = 0;
if (byteValues == null || byteValues.length <= 0)
return null;
String entries[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"a", "b", "c", "d", "e", "f" };
StringBuffer out = new StringBuffer(byteValues.length * 2);
for (int i = 0; i < byteValues.length; i++) {
singleChar = (byte) (byteValues[i] & 0xF0);
singleChar = (byte) (singleChar >>> 4);
// shift the bits down
singleChar = (byte) (singleChar & 0x0F);
out.append(entries[(int) singleChar]);
singleChar = (byte) (byteValues[i] & 0x0F);
out.append(entries[(int) singleChar]);
}
String rslt = new String(out);
return rslt;
}
Thanks a lot for all those who posted, cant thank you enough!

Categories

Resources