I'm struggeling with code from this page: http://www.androidsnippets.com/encrypt-decrypt-between-android-and-php
I want to send data from a server to an Android application and vice versa, but it should be sent as an encrypted string. However, I manage to encrypt and decrypt the string in PHP. But on Android the application crashes with the following error message when decrypting:
java.lang.Exception: [decrypt] unable to parse ' as integer.
This error occours here in the for-loop:
public static byte[] hexToBytes(String str) {
if (str==null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i=0; i<len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
}
System.out.println("Buffer: " + buffer);
return buffer;
}
}
This is by the way the string that should be decrypted: f46d86e65fe31ed46920b20255dd8ea6
You're talking about encrypting and decrypting, but you're showing code which simply turns numeric bytes (such as 0x4F) into strings (such as "4F") -- which may be relevant to your transfer of data (if you cannot transfer binary format), but completely unrelated to encryption/decryption.
Since the Android code you have contains only a single Integer parse, have you examined the input you're giving it? str.substring(i*2,i*2+2) apparently contains data other than [0-9A-F] when the exception occurs. You should start by examining the string you've received and comparing it to what you sent, to make sure they agree and they only contain hexadecimal characters.
Edit -- passing the string "f46d86e65fe31ed46920b20255dd8ea6" through your hexToBytes() function works flawlessly. Your input is probably not what you think it is.
Related
This is with reference to sipdroid data encrypt failed
I tried using XOR operation instead of reverse byte code for send packets and receive packets in SipdroidSocket.class.
I experienced same issue(too much noise)
Please guide me in encrypting and decrypting packets in SipdroidSocket.class
Sorry for late reply.I am posting the snippets of the code I tried. Please refer the original RtpSocket.java and SipdroidSocket.java classes for complete view. I am just putting the snippets here.
In RtpSocket.java , I took a static value and collected the packet's header length. Then used this header length in SipdroidSocket.java so as to remove the header part prior tweaking with the payload:
In SipdroidSocket.java, following editing were done in Send and Receive functions:
public void receive(DatagramPacket pack) throws IOException {
if (loaded) {
impl.receive(pack);
byte[] b = pack.getData(); // fetch data from receiver
int len = RtpSocket.header;
pack.setData(do_something(b, len)); // do the XORing to retrieve
// original data
} else {
super.receive(pack);
byte[] b = pack.getData();
int len = RtpSocket.header;
pack.setData(do_something(b, len));
}
}
public void send(DatagramPacket pack) throws IOException {
byte[] b = pack.getData(); // fetch original data
int len = RtpSocket.header;
pack.setData(do_something(b, len)); // replace with tweaked data
if (loaded)
impl.send(pack);
else
super.send(pack);
}
private byte[] do_something(byte[] b, int len) {
// TODO Auto-generated method stub
int new_buff_len = b.length - len;
byte[] new_buff = new byte[new_buff_len];
int i = 0;
for (i = len; i < b.length; i++) // separating header values
{
new_buff[i] = (byte) (b[i] ^ 0x43); // XORing original packet
// payload before sending and
// after receiving to get
// original data on both sides
}
return new_buff;
}
Kindly , try it and suggest me please.
Finally it worked ! Had to meddle with the other parts of the code . XOR operation now works fine and have attained the objective.
I am creating a SHA384 hash. I want to decode that hash. Is there any possible way to do this? Please help
Following is the code to get hash
public String getHash(String message) {
String algorithm = "SHA384";
String hex = "";
try {
byte[] buffer = message.getBytes();
MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(buffer);
byte[] digest = md.digest();
for(int i = 0 ; i < digest.length ; i++) {
int b = digest[i] & 0xff;
if (Integer.toHexString(b).length() == 1) hex = hex + "0";
hex = hex + Integer.toHexString(b);
}
return hex;
} catch(NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
A cryptographically secure hashing function is a function such that a given arbitrary length input is processed into a fixed length output in such a way that is not reversible (computationally infeasible). Such functions include MD5 and the SHA (Secure Hash Algorithm) family (1, 224, 256, 384, 512, etc).
Once you take the hash of the input there is no going back to the original input. This property can be used for verification of message integrity as hashing the identical message produces a identical hash.
The website you visited simply stores hashes and their inputs side by side and does a database lookup for your hash to attempt to find a possible input (if it was previously added to the database).
I am trying to implement an OTP generator for Blackberry OS10. I already use the reference implementation on Android side, you can find it here:
So I would like to convert it to C++ / QNX code and I have some troubles with hexadecimal conversion...
In java:
private static byte[] hexStr2Bytes(String hex){
// Adding one byte to get the right conversion
// Values starting with "0" can be converted
byte[] bArray = new BigInteger("10" + hex,16).toByteArray();
// Copy all the REAL bytes, not the "first"
byte[] ret = new byte[bArray.length - 1];
for (int i = 0; i < ret.length; i++)
ret[i] = bArray[i+1];
return ret;
}
In QNX:
QByteArray msg = QByteArray::fromHex(m.toLocal8Bit());
Problem is "m" start with '00' and so my final msg array is 0 length...
For example I try to encode the hex qstring:0000000002ca4e32
In blackberry: m=""
In Android: m="?M?"
So you can someone explain me how to deal with such a conversion ?
Thanks!
What I would do is to translate your Java function to plain C++, i.e. not QT format. Then adapt data type to QT.
I got to port some chat code from iOS to Android. Before sending the chat message to the socket, the iOS code uses the NSNonLossyASCIIStringEncoding class as parameter of the NSString::dataUsingEncoding.
How would you do it in Android? Same question about the opposite decoding.
Without doing that, for instance, the line breaks disappear in the message received on the other mobile.
Code on iOS:
NSData *data1 = [myStringTosend dataUsingEncoding:NSNonLossyASCIIStringEncoding];
NSString *goodValue = [[[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding] autorelease];
And decoding:
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
So far (and not correct), encoding on the Android side:
OutputStream os = socket.getOutputStream();
os.write(request.getBytes("UTF-8"));
os.flush();
And decoding:
while ((bytesRead = is.read(buffer, 0, BUFFER_SIZE)) >= 0) {
if (bytesRead > 0) response.append(new String(buffer, 0, bytesRead, "UTF-8"));
if (bytesRead < BUFFER_SIZE) break;
}
#portforwardpodcast is absolutely correct that you should, if possible, avoid ASCII encoding your utf8 and instead set up your stack to handle/store utf8 directly. That said, if you don't have the ability to change the behavior, the following code may be helpful.
While there's no published explanation of how NSNonLossyASCIIStringEncoding works, based on its output it looks like:
Bytes in the extended ASCII range (decimal values 128 - 255) are escaped using an octal encoding (e.g. ñ with decimal value 241 -> \361)
Non-ASCII code points are escaped in two byte chunks using a hex encoding (e.g. 😥 which takes up 32 bits with decimal value 128549 -> \ud83d\ude25)
So to encode:
public static String encodeToNonLossyAscii(String original) {
Charset asciiCharset = Charset.forName("US-ASCII");
if (asciiCharset.newEncoder().canEncode(original)) {
return original;
}
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < original.length(); i++) {
char c = original.charAt(i);
if (c < 128) {
stringBuffer.append(c);
} else if (c < 256) {
String octal = Integer.toOctalString(c);
stringBuffer.append("\\");
stringBuffer.append(octal);
} else {
String hex = Integer.toHexString(c);
stringBuffer.append("\\u");
stringBuffer.append(hex);
}
}
return stringBuffer.toString();
}
And to decode (this can be made more efficient by parsing the two types of encodings in lock step, rather as two separate passes):
private static final Pattern UNICODE_HEX_PATTERN = Pattern.compile("\\\\u([0-9A-Fa-f]{4})");
private static final Pattern UNICODE_OCT_PATTERN = Pattern.compile("\\\\([0-7]{3})");
public static String decodeFromNonLossyAscii(String original) {
Matcher matcher = UNICODE_HEX_PATTERN.matcher(original);
StringBuffer charBuffer = new StringBuffer(original.length());
while (matcher.find()) {
String match = matcher.group(1);
char unicodeChar = (char) Integer.parseInt(match, 16);
matcher.appendReplacement(charBuffer, Character.toString(unicodeChar));
}
matcher.appendTail(charBuffer);
String parsedUnicode = charBuffer.toString();
matcher = UNICODE_OCT_PATTERN.matcher(parsedUnicode);
charBuffer = new StringBuffer(parsedUnicode.length());
while (matcher.find()) {
String match = matcher.group(1);
char unicodeChar = (char) Integer.parseInt(match, 8);
matcher.appendReplacement(charBuffer, Character.toString(unicodeChar));
}
matcher.appendTail(charBuffer);
return charBuffer.toString();
}
Don't use NSNonLossyASCIIStringEncoding, use utf-8 encoding. I just solved this problem myself on ios+android+java spring backend, and it took me around 4 full days to figure everything out. Android can't display emojis, but this gives me full character support in almost all (or all not sure) languages. Here are the articles that helped me:
Must Read: http://blog.manbolo.com/2012/10/29/supporting-new-emojis-on-ios-6 http://blog.manbolo.com/2011/12/12/supporting-ios-5-new-emoji-encoding
See the hex bytes of a string inside the DB: How can I see raw bytes stored in a MySQL column?
Details about how to setup MySQL: http://technovergence-en.blogspot.com/2012/03/mysql-from-utf8-to-utf8mb4.html
In depth FAQ of utf8- http://www.unicode.org/faq/utf_bom.html#utf8-4
Details about the difference from notation: \ud83d\udc7d and hex value in memory: 0xF09F91BD http://en.wikipedia.org/wiki/UTF-8#Description
Use this to copy and paste characters in to see real hex byte values (works for emojis): http://perishablepress.com/tools/utf8-hex/index.php
Get Spring to support utf8 in urls (for GET params) http://forum.springsource.org/showthread.php?93728-RequestParam-doesn-t-seem-to-be-decoded Get Parameter Encoding http://forum.springsource.org/showthread.php?112181-Unable-to-Override-the-Spring-MVC-URL-decoding-which-uses-default-quot-ISO-8859-1-quot
My answer code is equivalent to IOS NSNonLossyASCIIStringEncoding for Android.
In your gradle put below depandancy.
compile 'org.apache.commons:commons-lang3:3.4'
then Put method to your Utils Class Like this
public static String encode(String s)
{
return StringEscapeUtils.escapeJava(s);
}
public static String decode(String s)
{
return StringEscapeUtils.unescapeJava(s);
}
then Simply call this method where you want to encode string or decode String like this
//for encode
String stencode = Utils.encode("mystring");
//for decode
String stdecode = Utils.decode("mystring")
All I need is convert byte[] to String. Then do something with that string and convert back to byte[] array. But in this testing I'm just convert byte[] to string and convert back to byte[] and the result is different.
to convert byte[] to string by using this:
byte[] byteEntity = EntityUtils.toByteArray(entity);
String s = new String(byteEntity,"UTF-8");
Then i tried:
byte[] byteTest = s.getBytes("UTF-8");
Then i complared it:
if (byteEntity.equals(byteTest) Log.i("test","equal");
else Log.i("test","diff");
So the result is different.
I searched in stackoverflow about this but it doesn't match my case. The point is my data is .png picture so the string converted is unreadable. Thanks in advance.
Solved
Using something like this.
byte[] mByteEntity = EntityUtils.toByteArray(entity);
byte[] mByteDecrypted = clip_xor(mByteEntity,"your_key".getBytes());
baos.write(mByteDecrypted);
InputStream in = new ByteArrayInputStream(baos.toByteArray());
and this is function clip_xor
protected byte[] clip_xor(byte[] data, byte[] key) {
int num_key = key.length;
int num_data = data.length;
try {
if (num_key > 0) {
for (int i = 0, j = 0; i < num_data; i++, j = (j + 1)
% num_key) {
data[i] ^= key[j];
}
}
} catch (Exception ex) {
Log.i("error", ex.toString());
}
return data;
}
Hope this will useful for someone face same problem. Thanks you your all for helping me solve this.
Special thanks for P'krit_s
primitive arrays are actually Objects (that's why they have .equals method) but they do not implement the contract of equality (hashCode and equals) needed for comparison. You cannot also use == since according to docs, .getBytes will return a new instance byte[]. You should use Arrays.equals(byteEntity, byteTest) to test equality.
Have a look to the answer here.
In that case my target was transform a png image in a bytestream to display it in embedded browser (it was a particular case where browser did not show directly the png).
You may use the logic of that solution to convert png to byte and then to String.
Then reverse the order of operations to get back to the original file.