i've a particular js function that encrypts some form inputs into base64, but I need to run it in my Java app. So my question is, how can i call that function inside a java class? Otherwise I'll have to translate it but I think will be more complicated. Here's some of js code:
function encode64(input)
{
//alert(input);
//alert(input);
input = escape(input);
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
var nMod =( input.length) % 3;
//alert(nMod);
//alert(input.length);
do
{
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = (((chr1 << 4) | (chr2 >> 4))& 0x3f);
enc3 = (((chr2 << 2) | (chr3 >> 6))& 0x3f);
enc4 = chr3 & 0x3f;
output = output +
keyStr.charAt(enc1) +
keyStr.charAt(enc2) +
keyStr.charAt(enc3) +
keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
if(nMod == 1)
{
chr1 = input.charCodeAt(i++);
enc1 = ((chr1 & 192)>>2);
enc2 = ((chr1 & 3) <<4);
enc3 = "=";
enc4 = "=";
output = output + keyStr.charAt(enc1)
+ keyStr.charAt(enc2)
+ keyStr.charAt(enc3)
+ keyStr.charAt(enc4);
}
if(nMod == 2)
{
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
enc1 = ((chr1 & 192)>>2);
enc2 = ((chr1 & 3) << 4 )|((chr2 & 0xf0) >> 4);
enc3 = ((chr2 & 15) <<2);
enc4 = "=";
output = output + keyStr.charAt(enc1)
+ keyStr.charAt(enc2)
+ keyStr.charAt(enc3)
+ keyStr.charAt(enc4);
}
return output;
}
Thanks so much!
but I think will be more complicated.
Why would it be more complicated? You can perfectly do that in Java. If your actual problem is already the first line
input = escape(input);
then it's good to know that the Java equivalent is the URLEncoder#encode(). As to the remnant of the coding, it's ultimately straightforward. Just replace var by String or char here and there, align the methods according java.lang.String API and you'll be fine.
Edit: for some downvoting nitpickers out here: I did NOT say that URLEncoder#encode() does the Base64 encoding. It just does URL encoding the same way as Javascript's escape() function does. That was just the first line of his to-be-translated Javascript code. Please read answers, do not scan answers.
Or better use commons-codec 's Base64 class
P.S. You do not "encrypt" into Base64 - you "encode"
You could do that using a javascript engine written in Java, but I think it's better to simply translate it into java.
I have used http://iharder.sourceforge.net/current/java/base64/ and it works.
Translate the code into Java - it will be quicker. (Or search for an existing example in Java!)
Related
I am calling a shared .dll function using JNA Java. From the documentation, the function can be invoked to receive parameters using Visual C++ as below;
PMSifEncodeKcdLcl(PCHAR ff, PCHAR Dta, BOOL Dbg, PCHAR szOpId, PCHAR szOpFirst, PCHAR szOpLast);
From the doc:
ff - A single ASCII character.
Dta - Points to a null-terminated string.
Dbg - a boolean flag
szOpId - points to a null-terminated string
szOpFirst - points to a null-terminated string
szOpLast - points to a null-terminated string
The string is built from a number of Data Fields. The format for each Data Field within the string is as follows:
RS FI data
RS = Record Separator.
Indicates the start of the Data Field. A single ASCII Record Separator [RS] character (hex 1E)
FI = Field Identifier - Indicates the type of data in the field. A single ASCII character.
data = the actual data. A number of ASCII characters, dependent on the Field Identifier. Sometimes the data is variable in length. The Record Separator of the following field indicates the end of a Data Field (or for the last field, the NULL character at the end of the string).
An Answer Code is returned in field ff. Answer Data (if any) is returned in field Dta
I have cross checked the JNA documentation to confirm field mappings but still no success. After trying for days. I came up with the code below;
My Java Code:
/* JNA interface class
*/
public class JNALocksInterface {
public interface LockLibrary extends StdCallLibrary {
LockLibrary INSTANCE = (LockLibrary) Native.loadLibrary("path_to_dll", LockLibrary.class);
public void PMSifEncodeKcdLcl(byte[] ff, byte[] dta, boolean debug, String szOpid, String szOpFirst, String szOpLast);
}
}
/*My Calling Class Code*/
JNALocksInterface.LockLibrary INSTANCE = JNALocksInterface.LockLibrary.INSTANCE;
String dta = "*R101*L101*TSingle Room*NMatu*FZachary*URegular Guest*D201805021347*O201805030111";
String ff = "A";
byte[] dataBytes = new byte[dta.length() + 1];
System.arraycopy(dta.getBytes("UTF-8"), 0, dataBytes, 0, dta.length());
dataBytes[dta.length()] = 0;
byte[] dtaByteArray = new byte[dta.length() + 1];
byte[] ffByteArray = ff.getBytes("UTF-8");
for (int i = 0; i < dataBytes.length; i++) {
String s1 = String.format("%8s", Integer.toBinaryString(dataBytes[i] & 0xFF)).replace(' ', '0');
// System.out.println(s1);
if((char)dataBytes[i] == '*')
{
dtaByteArray[i] = 30;
}
else{
int val = Integer.parseInt(s1, 2);
byte b = (byte) val;
dtaByteArray[i] = b;
}
}
byte[] commandCodeFinal = new byte[1];
for (int i = 0; i < ffByteArray.length; i++) {
String s2 = String.format("%8s", Integer.toBinaryString(ffByteArray[i] & 0xFF)).replace(' ', '0');
System.out.println(s2);
int val = Integer.parseInt(s2, 2);
byte b = (byte) val;
commandCodeFinal[i] = b;
}
String userNameBytes = "test";
String userFirstNameBytes = "test";
String userLastNameBytes = "test";
INSTANCE.PMSifEncodeKcdLcl(commandCodeFinal, dtaByteArray, false, userNameBytes, userFirstNameBytes, userLastNameBytes);
I am getting a wrong response on field ff and dta as shown below.
FF Response >> :
DTA Response >> 0101IR101L101TSingle RoomNMatuFZacharyURegular GuestD201805021347O2018050
I am replacing "*" with the ascii record separator.
Can someone show me how to correctly call the function using JNA? I've searched all over but still no success.
Solved IT. Used Unicode Field separator and used JNA Memory object and it Worked!
Was also using WIndows 10 64 bit. Changed to Windows 7 32 bit and it worked!!
Replaced the code with below snippet;
String fieldSeparator = "\u001e"
String dataTest = fieldSeparator+"R101"+fieldSeparator+"TSingle Room"+fieldSeparator+"FShujaa"+fieldSeparator+"NMatoke"
+ fieldSeparator+"URegular Guest"+fieldSeparator+"D201805040842"+fieldSeparator+"O201805051245";
String dataTestPadded = org.apache.commons.lang.StringUtils.rightPad(dataTest,30,'0');
System.out.println("Padded string >> " + dataTestPadded);
String data = dataTest;
//getPayloadToSend(payLoadSample) + (char)00;
String commandCode = "A";
Memory commandCodeMemory = new Memory(commandCode.length()+1);
commandCodeMemory.setString(0, commandCode);
Memory dataMemory = new Memory(data.length()+1);
dataMemory.setString(0, data);
//dataMemory.setString(1, "0");
System.out.println("Registerring >> " + INSTANCE.PMSifRegister("42860149", "BatchClient")) ;
INSTANCE.PMSifEncodeKcdLcl(commandCodeMemory, dataMemory, false, "ZKMATU", "zACHARY", "tESTING");
System.out.println("FF Response >> " + commandCodeMemory.getString(0));
System.out.println("DTA Response >> " + dataMemory.getString(0));
INSTANCE.PMSifUnregister();
I’m working in a project that use java 8, this project is about get some geographic information and work with this.
I already have done part of this work in python, and now I’m translating this part did in Python to java 8, well in Python I use this lines bellow to convert coordinates in Google format to Postgis format:
s1 = tuple(value.split(" "))
s2 = zip(s1[1::2], s1[::2])
For example:
I have a entrance like: value = "11.12345679 12.987655 11.3434454 12.1223323" and so on
The Python code above changes de entrance to:
s2 = "12.987655 11.12345679 12.1223323" and so on.
Changing the position of each coordinate pair, each entrance have thousands of coordinates.
To get the same effect with java (before java 8):
Using my knowledge of java (acquired before the java 8) I will need do that:
try {
String result = "", right = "", left = "";
String[] txt = str.split(" ");
for (int i = 0; i < txt.length; i += 2) {
right = txt[i];
left = txt[i + 1];
result += "," + left + " " + right;
}
return result.substring(1);
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
I will execute the java code above thousands of times, my question is: Java 8 has some new way to do this code above more like Python ?
My motivation to ask that question is because I came across with this news about Java 8:
List<String> someList = new ArrayList<>();
// Add some elements
someList.add("Generic (1.5)");
someList.add("Functional (8)");
// Open a stream
someList.stream()
// Turn all texts in Upper Case
.map(String::toUpperCase)
// Loop all elemnst in Upper Case
.forEach(System.out::println);
Updating:
The solution of Jean-François Savard was perfect using Java 8 like I asked, thank you so much Jean-Francois Savard
String str = "11.12345679 12.987655 11.3434454 12.1223323 11.12345679 12.987655 11.3434454 12.1223323";
String[] strs = str.split(" ");
str = IntStream.range(0, strs.length) .filter(i -> i % 2 == 0) .mapToObj(i -> strs[i + 1] + " " + strs[i]) .collect(Collectors.joining(","));
System.out.println(str);
>> 12.987655 11.12345679,12.1223323 11.3434454,12.987655 11.12345679,12.1223323 11.3434454
The solution shown by Vampire and Tukayi fit perfectly in my problem, thanks a lot guys
String str = "11.12345679 12.987655 11.3434454 12.1223323 11.12345679
12.987655 11.3434454 12.1223323";
str = str.replaceAll("([^\\s]+) ([^\\s]+)(?: |$)", ",$2 $1").substring(1);
System.out.println(str);
Define the following in your class to precompile a Regex pattern
private static final Pattern pattern = Pattern.compile("([^ ]++) ([^ ]++)(?: |$)");
Then in your method use
if ((new StringTokenizer(str, " ").countTokens() % 2) == 1) {
return null;
}
return pattern.matcher(str).replaceAll(",$2 $1").substring(1);
to get the same result as in your original code.
If you depend on using Streams why-o-ever, here a Streams solution
String[] strs = str.split(" ");
return IntStream.range(0, strs.length)
.filter(i -> i % 2 == 0)
.mapToObj(i -> strs[i + 1] + " " + strs[i])
.collect(Collectors.joining(","));
Java 8 added (among other things) Lambdas, Streams and Functional interfaces.
You can use streams to simplify looping over objects. But the syntax like you see in Python isn't the same as in java like that.
I have the snippet of java code.
functionReturnValue = String.format("%1$2s", jDay).replace(' ', '0') + "/" + String.format("%1$2s", i).replace(' ', '0') + "/" + dateIn.substring(0, 4);
What is the swift equivalent of this?
This is what I have so far
let string1 = String(format: "%1$2s", jDay);
let replacedString = String(string1.characters.map{$0 == " " ? "0" : $0})
let string2 = String(format: "%1$2s", i);
let replacedString2 = String(string2.characters.map{$0 == " " ? "0" : $0})
let string3 = dateIn[year];
let stringFinal = replacedString + "/" + replacedString2 + "/" + string3;
Format strings in Swift and in Java are different, so you cannot use %1$2s for your format. Also, since the call of replace in your Java code is there to add leading zeros, you could replace it with a call of format. Finally, use string interpolation to construct the final string:
let s1 = String(format: "%02d", jDay)
let s2 = String(format: "%02d", i)
let s3 = dateIn[year]
let stringFinal = "\(s1)/\(s2)/\(s3)"
Just in case anyone is wondering (like I was) you can have format strings with multiple conversions, e.g.:
let hourPart = 5
let minutePart = 8
let isPm = true
let retStr = String(format: "%d:%02d %#", hourPart, minutePart, isPm ? "PM" : "AM")
gives "5:08 PM"
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.
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.