About Java Android BASE64 decoding to ASCII String - java

I have Base64 string data that i have received from a service.
I am able to decode this data and get byte array.
But when i create a new string from that byte array, my server is not being able to read that data properly.
But this same process in C language of Linux based device is working fine on my server side. That is to say, if i (Base64) decode that same string (using OpenSSL and get char array) on that device and send it to my server, the server is able to read that properly.
Now, i tried a sample code in eclipse to understand the problem. Below is the sample,
String base1 =
"sUqVKrgErEId6j3rH8BMMpzvXuTf05rj0PlO/eLOoJwQb3rXrsplAl28unkZP0WvrXRTlpAmT3Y
ohtPFl2+zyUaCSrYfug5JtVHLoVsJ9++Afpx6A5dupn3KJQ9L9ItfWvatIlamQyMo2S5nDypCw79
B2HNAR/PG1wfgYG5OPMNjNSC801kQSE9ljMg3hH6nrRJhXvEVFlllKIOXOYuR/NORAH9k5W+rQeQ
7ONsnao2zvYjfiKO6eGleL6/DF3MKCnGx1sbci9488EQhEBBOG5FGJ7KjTPEQzn/rq3m1Yj9Le/r
KsmzbRNcJN2p/wy1xz9oHy8jWDm81iwRYndJYAQ==";
byte[] b3 = Base64.getDecoder().decode(base1.getBytes());
System.out.println("B3Len:" + b3.length );
String s2 = new String(b3);
System.out.println("S2Len:" + s2.length() );
System.out.println("B3Hex: " + bytesToHex(b3) );
System.out.println("B3HexLen: " + bytesToHex(b3).length() );
byte[] b2 = s2.getBytes();
System.out.println("B2Len:" + b2.length );
int count = 0;
for(int i = 0; i< b3.length; i++) {
if(b3[i] != b2[i]) {
count++;
System.out.println("Byte: " + i + " >> " + b3[i] + " != " + b2[i]);
}
}
System.out.println("Count: " + count);
System.out.println("B2Hex: " + bytesToHex(b2) );
System.out.println("B2HexLen: " + bytesToHex(b2).length() );
Below is output:
B3Len:256
S2Len:256
B3Hex:
b14a952ab804ac421dea3deb1fc04c329cef5ee4dfd39ae3d0f94efde2cea09c106f7ad7aeca
65025dbcba79193f45afad74539690264f762886d3c5976fb3c946824ab61fba0e49b551cba1
5b09f7ef807e9c7a03976ea67dca250f4bf48b5f5af6ad2256a6432328d92e670f2a42c3bf41
d8734047f3c6d707e0606e4e3cc3633520bcd35910484f658cc837847ea7ad12615ef1151659
65288397398b91fcd391007f64e56fab41e43b38db276a8db3bd88df88a3ba78695e2fafc317
730a0a71b1d6c6dc8bde3cf0442110104e1b914627b2a34cf110ce7febab79b5623f4b7bfaca
b26cdb44d709376a7fc32d71cfda07cbc8d60e6f358b04589dd25801
B3HexLen: 512
B2Len:256
Byte: 52 >> -112 != 63
Byte: 175 >> -115 != 63
Byte: 252 >> -99 != 63
Count: 3
B2Hex:
b14a952ab804ac421dea3deb1fc04c329cef5ee4dfd39ae3d0f94efde2cea09c106f7ad7aeca
65025dbcba79193f45afad7453963f264f762886d3c5976fb3c946824ab61fba0e49b551cba1
5b09f7ef807e9c7a03976ea67dca250f4bf48b5f5af6ad2256a6432328d92e670f2a42c3bf41
d8734047f3c6d707e0606e4e3cc3633520bcd35910484f658cc837847ea7ad12615ef1151659
65288397398b91fcd391007f64e56fab41e43b38db276a3fb3bd88df88a3ba78695e2fafc317
730a0a71b1d6c6dc8bde3cf0442110104e1b914627b2a34cf110ce7febab79b5623f4b7bfaca
b26cdb44d709376a7fc32d71cfda07cbc8d60e6f358b04583fd25801
B2HexLen: 512
I understand that there are extended characters in this string.
So, here we can see that the reconverting the hex to string is not working properly, because of the differences in the byte arrays.
I actually need this to work because, i have much larger Base64 string than the one in this sample that i need to send to my server which is trying to read ASCII string.
Or,
Can anyone give me a solution that can give me an ASCII String output that is identical to char array output from C language (OpenSSL decoding) on Linux device.

Related

How to replace a static string with a variable and convert to long?

I have the following code to generate sequential Mac Addresses. The code works well if I statically define the string when creating the hextint. However, if I change the string to a variable, as seen below, I get an error:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "6CDFFB6000000A
"
I'm sure I'm missing something simple here. Why is the string as a variable not converting? Any help is appreciated.
String macAddr = last_mac.getText();
// int qty = Integer.parseInt(label_qty.getText());
System.out.println("String to convert: " + macAddr);
// long hexint = Long.parseLong("6CDFFB60000000", 16);
long hexint = Long.parseLong(macAddr, 16);
System.out.println("String converted to Long:" +hexint);
System.out.println("10+ previous number:" + (10+hexint));
System.out.println("Convert back to hex: " + Long.toHexString(10+hexint).toUpperCase());
for(int i = 1; i < 10+1; i++){
System.out.println(i +" MAC: " + Long.toHexString(hexint + i).toUpperCase());
macAddr = Long.toHexString(hexint + i).toUpperCase();
}
Your text contains a trailing space. You should remove it by trim() method. Try the following code & it should work for you.
String macAddr = last_mac.getText().trim();

SMPP Submit Long Message and message split

We are using SMPP cloud-hopper library to SMS long long messages to SMS gateway Innovativetxt.com, but it seems like when we split following the long message TO 140 bytes each part. The number of characters in each message gets to 134 character.
However industry standard is kind of 153 character shall be for each part of GSM Encoded long message. Is it something wrong we are doing by having only 134 character when we split via 140 byte? If we trying to submit greater than 140 bytes message, the gateway provider rejects it with message oversized message body.
Shall be split the message to 153 character each to sbumit to SMSC, instead spiting the messages via 140 bytes each.
What is the best way to split long message? By message size i.e 140 bytes or message characters count?
Anyone faced same issues via cloudhopper or other Java-based Library what we shall do.
It's a common confusion. You are doing everything right. Message lengths may be 160 chars (7-bit GSM 03.38), 140 chars (8-bit Latin), 70 chars (16-bit UCS-2). Notice: 160 * 7 == 140 * 8 == 70 * 16.
When you split a long message additional info like total parts number and part index is stored in the message body, so-called User Data Header (UDH). This header also takes place. So, with UDH you left with 153 GSM chars (7-bit), 134 chars/bytes (8-bit) payload or 67 2bytes-unicode chars (16-bit)
See also http://www.nowsms.com/long-sms-text-messages-and-the-160-character-limit
The UDH is 6 bytes long for Contatenated message 8-bit as in your case.
UDH structure
0x05: Length of UDH (5 bytes to follow)
0x00: Concatenated message Information Element (8-bit reference number)
0x03: Length of Information Element data (3 bytes to follow)
0xXX: Reference number for this concatenated message
0xYY: Number of fragments in the concatenated message
0xZZ: Fragment number/index within the concatenated message
Total message length, bits: 160*7 = 140*8 = 1120
UDH length, bits: 6*8 = 48
Left payload, bits: 1120-48 = 1072
For GSM 03.38 you get 1072/7 = 153 GSM (7-bit) chars + 1 filling unused bit.
For Latin you get 1072/8 = 134 (8-bit) chars.
For UCS-2 you get 1072/16 = 67 (16-bit) chars.
As you can see 153 GSM chars equals to 134 bytes minus 1 bit. Probably these 134 chars is what Java reports you. But once you split your long text message you end up with a binary message containing both text and UDH. And you should treat the message as binary. I suggest you to make binary dumps out of the resulting parts and investigate them.
Hello See sample method for sending both short or long SMS
public synchronized String sendSMSMessage(String aMessage,
String aSentFromNumber, String aSendToNumber,
boolean requestDeliveryReceipt) {
byte[] textBytes = CharsetUtil.encode(aMessage,
CharsetUtil.CHARSET_ISO_8859_1);
try {
SubmitSm submitMsg = new SubmitSm();
// add delivery receipt if enabled.
if (requestDeliveryReceipt) {
submitMsg
.setRegisteredDelivery(SmppConstants.REGISTERED_DELIVERY_SMSC_RECEIPT_REQUESTED);
}
submitMsg.setSourceAddress(new Address((byte) 0x03, (byte) 0x00,
aSentFromNumber));
submitMsg.setDestAddress(new Address((byte) 0x01, (byte) 0x01,
aSendToNumber));
if (textBytes != null && textBytes.length > 255) {
submitMsg.addOptionalParameter(new Tlv(SmppConstants.TAG_MESSAGE_PAYLOAD, textBytes, "message_payload"));
}else{
submitMsg.setShortMessage(textBytes);
}
logger.debug("About to send message to " + aSendToNumber
+ ", Msg is :: " + aMessage + ", from :: "
+ aSentFromNumber);
SubmitSmResp submitResp = smppSession.submit(submitMsg, 15000);
logger.debug("Message sent to " + aSendToNumber
+ " with message id " + submitResp.getMessageId());
return submitResp.getMessageId();
} catch (Exception ex) {
logger.error("Exception sending message [Msg, From, To] :: ["
+ aMessage + ", " + aSentFromNumber + ", " + aSendToNumber,
ex);
}
logger.debug("Message **NOT** sent to " + aSendToNumber);
return "Message Not Submitted to " + aSendToNumber;
}

Receive string from processing to arduino

I want to receive a string from processing to arduino. I am writing a string(Basically an array of single digits in the form of string eg: <0213> is an array: 0 2 1 3). I am able to write it to port but how do I receive it on arduino? Following code is to send to arduino.
int[] send={0,2,3,1};
myPort =new Serial(this,"/dev/ttyACM0", 9600);
String theStg = "<" + nf(send[0], 3) +
" " + nf(send[1], 3) +
" " + nf(send[2], 3) +
" " + nf(send[3], 3) +
">";
myPort.write(theStg);
if you were using a string of char*, rather than the String Class, then you could use avrlibc's strtok() command.
This has been addressed previously(click here)
And here is a nice function you can simply add to your code to do the equivalent of the strtok(), but on a String object.

JIS X 0208 conversion: how to handle unified (merged) codepoints

I'm trying to convert Java characters to JIS X 0208 "x-JIS0208" encoding (or any compatible, like EUC-JP, but not Shift-JIS), but I want unified (merged) codepoints to be handled correctly.
For example, 高 is assigned to row 25 column 66 in this JISX0208 chart, and a look-alike character 髙, while classified as an unassigned codepoint, is merged with the former. I quote from wikipedia: "both the form [ ] (高) and the less common form with a ladder-like construction (髙) are subsumed into the same code point".
I tried this in code the code below, and whatever encoding I try, I always get either an exception or the unassigned-character-placeholder ? (either ASCII or full-width).
Is there a way, perhaps a different endoding or an entirely different way of converting, so both these characters return the same codepoint? Alternatively, is there an API to find such characters so I can merge them before converting?
static Charset charset1 = Charset.forName("x-JIS0208");
static Charset charset2 = Charset.forName("EUC-JP");
static Charset[] charsets = {charset1, charset2};
static CharBuffer in = CharBuffer.allocate(1);
public static void main(String[] args) throws Exception
{
CharsetEncoder[] encoders = new CharsetEncoder[charsets.length];
for (int i = 0; i < charsets.length; i++)
encoders[i] = charsets[i].newEncoder();
char[] testChars = {' ', 'A', '?', '亜', '唖', '蔭', '高', '髙'};
for (char ch : testChars)
{
System.out.print("'" + ch + "'\t(" + Integer.toHexString(ch) + ")\t=");
for (int i = 0; i < charsets.length; i++)
{
System.out.print("\t" + interpret(encode1(encoders[i], ch)));
System.out.print("\t" + interpret(encode2(charsets[i], ch)));
}
System.out.println();
}
}
private static String interpret(int i)
{
if (i == -1)
return "excepti";
if (i < 0x80)
return "'" + (char)i + "'";
return Integer.toHexString(i);
}
private static int encode1(CharsetEncoder encoder, char ch)
{
in.rewind();
in.put(ch);
in.rewind();
try
{
ByteBuffer out = encoder.encode(in);
if (out.limit() == 1)
return out.get(0) & 0xFF;
return out.get(1) & 0xFF | (out.get(0) & 0xFF) << 8;
}
catch (CharacterCodingException e)
{
return -1;
}
}
private static int encode2(Charset charset, char ch)
{
in.rewind();
in.put(ch);
in.rewind();
ByteBuffer out = charset.encode(in);
if (out.limit() == 1)
return out.get(0) & 0xFF;
return out.get(1) & 0xFF | (out.get(0) & 0xFF) << 8;
}
The output:
' ' (3000) = 2121 2121 a1a1 a1a1
'A' (ff21) = 2341 2341 a3c1 a3c1
'?' (ff1f) = 2129 2129 a1a9 a1a9
'亜' (4e9c) = 3021 3021 b0a1 b0a1
'唖' (5516) = 3022 3022 b0a2 b0a2
'蔭' (852d) = 307e 307e b0fe b0fe
'高' (9ad8) = 3962 3962 b9e2 b9e2
'髙' (9ad9) = excepti 2129 excepti '?'
Note: I'm only interested in converting single characters, lots of them, not strings or streams, so I actually prefer a different method (if exists) that doesn't allocate a ByteBuffer every conversion.
髙 is not contained in JIS X 0208, but is containd in Microsoft Windows code page 932 (MS932). This is a variant of Shift JIS encoding, and is a superset of JIS X 0208 charset.
You should use the name "Windows-31j" for MS932, like:
Charset.forName("Windows-31j");
rather than Charset.forName("x-JIS0208");.
EDIT
The mapping table for some characters like 𨦇 and 鋏 (scissors) is distributed from the government of Japan, like National Tax Agency (see JIS縮退マップ(Ver.1.0.0)) .
But these mapping tables don't contain the character 髙. I think this is because 髙 is not contained in JIS X 0208 nor JIS X 0213.
So, I think you will have to replace 髙 with 高 manually (with String#replaceAll()), or make your own custom Charset with CharsetProvider.
I only knew that in the spec "ARIB STD-B24" (for ISDB-T 1seg in JP), this character is coding with DRCS pattern data, from DRCS-1 to DRCS-15, and each set consists of 94
characters.

Java encryption and Force.com apex encryption

I need to convert this java code in force.com apex. i tried to use Crypto class to get same encryption but not getting how can i get same value for the variable "fingerprintHash" in the last in APEX . Can Anyone help me in this technical issue?
Random generator = new Random();
sequence =Long.parseLong(sequence+""+generator.nextInt(1000));
timeStamp = System.currentTimeMillis() / 1000;
try {
SecretKey key = new SecretKeySpec(transactionKey.getBytes(), "HmacMD5");
Mac mac = Mac.getInstance("HmacMD5");
mac.init(key);
String inputstring = loginID + "^" + sequence + "^" + timeStamp + "^" + amount + "^";
byte[] result = mac.doFinal(inputstring.getBytes());
StringBuffer strbuf = new StringBuffer(result.length * 2);
for (int i = 0; i < result.length; i++) {
if (((int) result[i] & 0xff) < 0x10) {
strbuf.append("0");
}
strbuf.append(Long.toString((int) result[i] & 0xff, 16));
}
fingerprintHash = strbuf.toString(); //need this result for variable x_fp_hash
The apex code I was trying is :-
String API_Login_Id='6########';
String TXn_Key='6###############';
String amount='55';
sequence = '300';
long timeStamp = System.currentTimeMillis()/1000;
String inputStr = API_Login_Id + '^' + sequence + '^' + timeStamp + '^' + amount + '^';
String algorithmName = 'hmacMD5';
Blob mac = Crypto.generateMac(algorithmName,Blob.valueOf(inputStr),Blob.valueOf( TXn_Key));
String macUrl =EncodingUtil.urlEncode(EncodingUtil.base64Encode(mac), 'UTF-8');
The problem would seem to be that you are hex encoding the output on the javaside, but base64 encoding the output on the apex side, try using EncodingUtils.convertToHex instead of EncodingUtils.base64Encode
You look like you're heading along the right lines with regards to the encryption, however you're using a time stamp as part of your input string, and so unless you're astronomically lucky you're always encoding different strings. While you're working on porting the code, remove the timestamp so that you can be sure your input strings are the same - if they're not the same then you'll never get the same result.
Once you've established that your encryption is working as desired, then you can put the timestamp back into the code safe in the knowledge that it'll be functioning the same way as the original java code.

Categories

Resources