Protobuf : pass protobuf message from Javascript to C++ WebAssembly module - javascript

I would like to pass a protobuf message from Javascript to a C++ WebAssembly module.
I do receive, and can successfully parse the simpler protobuf messages on the C++ side, however, protobuf is failing to parse the less-simple protobuf messages.
Here is the code that I am using :
goog.module('protobufMessageGenerator');
goog.require('proto.my_proto.MyMessage');
function generateMyMessage() {
var msg = new proto.my_proto.MyMessage()
var internal = new proto.my_proto.MyMessageInternal()
internal.setAccentColor("#CC1D24")
internal.setLogo("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")
msg.setInternal(internal)
return msg
}
Using the google-closure-compiler, I compile this protobuf message generator to pure Javascript.
I use this code to pass the message to the C++ WebAssembly module :
function sendMessage() {
Module.self().setMyMessage(module$contents$protobufMessageGenerator_generateMyMessage().serializeBinary())
}
sendMessage()
I receive the message on the C++ side using this code :
void JavascriptPublicInterface::setMyMessage(const QString &myMessage)
{
if (_myMessage != myMessage)
{
_myMessage = myMessage;
emit myMessageChanged();
}
}
void JavascriptPublicInterface::setMyMessageEMS(const std::string &myMessage)
{
setMyMessage(QString::fromStdString(myMessage));
}
//...
void startListeningToMyMessage(std::function<void(euf_proto::MyMessage myMessage)> listener)
{
const auto changedListener = [listener]() {
const auto newMyMessageString = JavascriptPublicInterface::self()->myMessage();
my_proto::MyMessage myMessagePb;
if (myMessagePb.ParseFromString(newMyMessageString.toStdString()))
{
qDebug() << "C++ : Successfully parsed new MyMessage: " << newMyMessageString;
}
else
{
qDebug() << "C++ : Failed to parse new MyMessage: " << newMyMessageString;
}
qDebug() << "MyMessage received: " << QString::fromStdString(myMessagePb.DebugString());
listener(myMessagePb);
};
if (!QObject::connect(JavascriptPublicInterface::self(), &JavascriptPublicInterface::myMessageChanged, changedListener))
{
throw std::runtime_error("Failed to connect to JavascriptPublicInterface myMessageChanged");
}
}
In the Javascript console I see : "C++ : Failed to parse new MyMessage: ..."
I guess that it can be related to the fact that Javascript is using UTF-16 and C++ is using UTF-8 encoding (because the messages that are UTF-8 only can be successfully parsed), so I tried to fix the sending and receiving like this:
//For more info see : https://emscripten.org/docs/api_reference/emscripten.h.html?highlight=stringtoutf8
function convertUtf16ToUtf8(input) {
var uint8Arr = input
var jsString = String.fromCharCode.apply(null, uint8Arr)
var lengthBytes = lengthBytesUTF8(jsString)+1
var stringOnWasmHeap = _malloc(lengthBytes)
stringToUTF8(jsString, stringOnWasmHeap, lengthBytes)
return stringOnWasmHeap
}
function sendMessage() {
var myMessage = convertUtf16ToUtf8(module$contents$protobufMessageGenerator_generateMyMessage().serializeBinary())
Module.self().setMyMessage(myMessage)
_free(myMessage)
}
sendMessage()
And I modified the parsing on the C++ side like this :
void JavascriptPublicInterface::setMyMessageEMS(const int pointer)
{
const char* msg = (char*)pointer;
setMyMessage(QString::fromStdString(msg));
}
But I still get this error : "C++ : Failed to parse new MyMessage: ..."
How could I fix this?
(I am using protobuf 3.19.1 (same version on both the Javascript and the C++ side).)
UPDATE :
In case if I modify my code, so it is passing a simple string as logo, then I can successfully parse the protobuf message on the C++ side :
internal.setLogo("logo")
So I guess that the issue is with this field.
The original string is a base64 encoded image.
What should I do with this string to fix the parsing?

I found the solution.
This stackoverflow post described a really similar issue, and it helped me to fix my parsing as well :
Protobuf: Serialize/DeSerialize C++ to Js
Here is my updated code, which works well :
I had to update the Javascript side :
function sendMessage() {
Module.self().setMyMessage(module$contents$protobufMessageGenerator_generateMyMessage().serializeBinary().toString())
}
sendMessage()
and the C++ side :
namespace
{
QByteArray decryptProtobufMessage(const std::string &str)
{
QStringList strList = QString::fromStdString(str).split(',');
QByteArray bytedata;
foreach (const QString &str, strList)
{
bytedata += (str.toUInt());
}
return bytedata;
}
} // namespace
void JavascriptPublicInterface::setMyMessage(const QByteArray &myMessage)
{
if (_myMessage != myMessage)
{
_myMessage = myMessage;
emit myMessageChanged();
}
}
void JavascriptPublicInterface::setMyMessageEMS(const std::string &myMessage)
{
setMyMessage(decryptProtobufMessage(myMessage));
}
//...
void startListeningToMyMessage(std::function<void(euf_proto::MyMessage myMessage)> listener)
{
const auto changedListener = [listener]() {
const auto newMyMessageByteArray = JavascriptPublicInterface::self()->myMessage();
my_proto::MyMessage myMessagePb;
if (myMessagePb.ParseFromArray(newMyMessageByteArray.data(), newMyMessageByteArray.size()))
{
qDebug() << "C++ : Successfully parsed new MyMessage: " << newMyMessageByteArray;
}
else
{
qDebug() << "C++ : Failed to parse new MyMessage: " << newMyMessageByteArray;
}
qDebug() << "MyMessage received: " << QString::fromStdString(myMessagePb.DebugString());
listener(myMessagePb);
};
if (!QObject::connect(JavascriptPublicInterface::self(), &JavascriptPublicInterface::myMessageChanged, changedListener))
{
throw std::runtime_error("Failed to connect to JavascriptPublicInterface myMessageChanged");
}
}

Related

Android Capacitor JS Plugin does not reply

I am working on a java plugin that is supposed to recieve some info from a js vue3 program and then do a URL post operation, and then return some of the info found back to the js code. I am using capacitor and android. This is my error message:
2022-08-22 13:46:23.773 27544-27544/org.theguy.GptEtc E/Capacitor/Console: File: http://localhost/js/app.6577adf2.js - Line 1 - Msg: Uncaught (in promise) SyntaxError: Unexpected token o in JSON at position 1
I think this means that something other than valid JSON is being delivered to the js code. I know that the app is delivering info to the java android class. This is some of my java code.
#CapacitorPlugin(name = "URLPOST")
public class PluginURLPost extends Plugin {
#PluginMethod()
public void post(PluginCall call) {
String post_url = call.getString("post_url", "");
String bearer = call.getString("bearer", "pipeline_");
JSObject ret = new JSObject();
try {
String value = this.doPost(post_url, bearer);
System.out.println("value " + value);
Gson gson = new Gson();
JsonReader reader = new JsonReader(new StringReader(value));
ResultPreview preview = gson.fromJson(reader, ResultPreview.class);
String val = preview.getResult_preview()[0][0];
val = "result string here."; // <-- add this for easy testing
ret.put("response_text", val.replace("\n", "\\n"));
System.out.println("response here: " + val);
}
catch (Exception e) {
e.printStackTrace();
}
//call.setKeepAlive(true);
call.resolve(ret);
}
OkHttpClient client = new OkHttpClient();
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
String doPost(String post_url, String bearer ) throws IOException {
// ... do some post request here ...
return response_body;
}
}
class ResultPreview {
#SerializedName("result_preview")
String [][] result_preview ;
public void setResult_preview(String[][] result) {
this.result_preview = result;
}
public String[][] getResult_preview() {
return this.result_preview;
}
}
This is some of my js code.
import { registerPlugin } from "#capacitor/core";
const URLPOST = registerPlugin("URLPOST");
const request = {
"line": line,
"pipeline_model": details[engine]["app_model"].trim(),
"bearer": details[engine]["api_key"].trim(),
"post_url": details[engine]["url"].trim(),
"length": 25,
"top_k": 50
};
console.log("request", request);
var {response_text} = await URLPOST.post(request);
console.log("response_text 1",response_text);
I don't know what to do.
I tried this, and things work better. I don't know if this is the ultimate solution.
#PluginMethod()
public void post(PluginCall call) {
bridge.saveCall(call); // <-- add this
call.release(bridge); // <-- add this
String pipeline_model = call.getString("pipeline_model", "pipeline_");
String post_url = call.getString("post_url", "");
JSObject ret = new JSObject();
try {
String value = this.doPost(post_url);
Gson gson = new Gson();
JsonReader reader = new JsonReader(new StringReader(value));
ResultPreview preview = gson.fromJson(reader, ResultPreview.class);
String val = preview.getResult_preview()[0][0];
ret.put("response_text", val.replace("\n", "\\n"));
System.out.println("response here: " + val);
}
catch (Exception e) {
e.printStackTrace();
}
call.resolve(ret);
}
This is not found on the capacitor site, but instead I found it digging around the internet.

Error in JavaScript Elliptic curve cryptography to import the private key: Bad private key?

I want to encrypt and decrypt the message based on ECIES using this library JavaScript Elliptic curve cryptography library.
I want to import my private key and get the public key from it because I do not have a new private key generated each time I run the code.
The code:
var eccrypto = require("eccrypto");
var privateKeyB = 'efae5b8156d785913e244c39ca5b9bee1a46875d123d2f49bbeb0a91474118cf';
var publicKeyB = eccrypto.getPublic(privateKeyB);
console.log(publicKeyB.toString('hex'))
// Encrypting the message for B.
eccrypto.encrypt(publicKeyB, Buffer.from("msg to b")).then(function(encrypted) {
// B decrypting the message.
eccrypto.decrypt(privateKeyB, encrypted).then(function(plaintext) {
console.log("Message to part B:", plaintext.toString());
});
});
However, the code is not working and shows this error:
throw new Error(message || "Assertion failed");
^
Error: Bad private key
eccrypto.getPublic() expects a Buffer as argument, not a string. Try this instead:
var eccrypto = require("eccrypto");
var privateKeyB = Buffer.from('efae5b8156d785913e244c39ca5b9bee1a46875d123d2f49bbeb0a91474118cf', 'hex');
var publicKeyB = eccrypto.getPublic(privateKeyB);
console.log(publicKeyB.toString('hex'))
// Encrypting the message for B.
eccrypto.encrypt(publicKeyB, Buffer.from("msg to b")).then(function(encrypted) {
// B decrypting the message.
eccrypto.decrypt(privateKeyB, encrypted).then(function(plaintext) {
console.log("Message to part B:", plaintext.toString());
});
});

Generate HMAC SHA Algorithm using URI and Key

I wrote a Java program which generates HMAC SHA hash code, But due to some reason I have to write the same code in NodeJs/JavaScript. I tried googling around but did not get anything. In this Java code, I am passing URI and Key as arguments, to generate the hash code, where URI contains Timestamp.
The java code is as :
public static String calcMAC(String data, byte[] key) throws Exception {
String result=null;
SecretKeySpec signKey = new SecretKeySpec(key, SecurityConstants.HMAC_SHA1_ALGORITHM);
Mac mac = Mac.getInstance(SecurityConstants.HMAC_SHA1_ALGORITHM);
mac.init(signKey);
byte[] rawHmac;
try {
rawHmac = mac.doFinal(data.getBytes("US-ASCII"));
result = Base64.encodeBase64String(rawHmac);
} catch (Exception e) {
e.printStackTrace();
}
return result.trim();
}
public static void main(String args[]) {
String timestamp = args[0];
String key = "d134hjeefcgkahvg32ajkdbaff84ff180";
String out = null;
try {
out = calcMAC("/req?app_id=47ca34" + timestamp + "=2018-05-22T12:02:15Z",
key.getBytes());
System.out.println(URLEncoder.encode(out, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
Is it possible to achieve the same goal in NodeJs/JavaScript?
Note:: I have to call this script from Postman pre-request script.
The crypto module should do this for you, you can substitute the 'data' variable with whatever you want to hash:
const crypto = require('crypto');
const data = 'The fault dear Brutus lies not in our stars';
const key = Buffer.from('d134hjeefcgkahvg32ajkdbaff84ff180', 'utf8');
const hash = crypto.createHmac('sha1', key).update(data).digest('base64');
const uriEncodedHash = encodeURIComponent(hash);
console.log('Hash: ' + uriEncodedHash);
Hashing the data in both Java and Node.js gives me the result (URI Encoded) of:
TJJ3xj93m8bfVpGoucluMQqkB0o%3D
The same Java code would be:
public static void main(String args[]) {
String data = "The fault dear Brutus lies not in our stars";
String key = "d134hjeefcgkahvg32ajkdbaff84ff180";
String out = null;
try {
out = calcMAC(data, key.getBytes());
System.out.println(URLEncoder.encode(out, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
Again, we can put anything into 'data' we want.

j2v8 Object from nodejs script not accesible

I try to run a nodeJS script with j2v8 in my Java project and it runs normally but i can't get the Array or any other JScript Objects although this functionality is offered through j2v8. Additionally the script uses a npm module called Blocktrail which generates the Array. The call for the Object is in the function testExportAnalyzer(). Here it throws that the Object does not contain "test". Please, can anyone explain how i can use the variables or the needed Array in my Java Code or what I do wrong?
public ScriptLoader(String adr) {
address = adr;
addressInformation = null;
NODE_SCRIPT = ""
+"var test = \"123456\";\n"
+"var blocktrail = require('/blocktrail-sdk');\n"
+"var addressInformation = null;\n"
+"var client = blocktrail.BlocktrailSDK({apiKey : \"xxxxxx\", apiSecret : \"xxxxxx\"});\n"
+"client.address(\""+address+"\", function(err, address) {\n"
+" if (err) {\n"
+" console.log('address ERR', err);\n"
+" return;\n"
+" }\n"
+" addressInformation = address;"
+"console.log('address:', address['address'], 'balance:', address['balance'] / blocktrail.COIN, 'sent and received in BTC:', address['sent'] / blocktrail.COIN, address['received'] / blocktrail.COIN, 'number of transactions:', address['total_transactions_out'], address['total_transactions_in']);\n"
+"});\n"
+"\n"
+"client.addressTransactions(\""+address+"\", {limit: 100}, function(err, address_txs) {\n"
+" console.log('address_transactions', address_txs['data'].length, address_txs['data'][0]);\n"
+"});";
}
public void executeAnalyzerScript() throws IOException {
final NodeJS nodeJS = NodeJS.createNodeJS();
JavaCallback callback = new JavaCallback() {
public Object invoke(V8Object receiver, V8Array parameters) {
return "Hello, JavaWorld!";
}
};
nodeJS.getRuntime().registerJavaMethod(callback, "someJavaMethod");
File nodeScript = createTemporaryScriptFile(NODE_SCRIPT, "addressScript");
nodeJS.exec(nodeScript);
while(nodeJS.isRunning()) {
nodeJS.handleMessage();
}
nodeJS.release();
}
public void testExportAnalyzer() throws IOException {
NodeJS nodeJS = null;
File testScript = createTemporaryScriptFile(NODE_SCRIPT, "Test");
nodeJS = NodeJS.createNodeJS();
V8Object exports = nodeJS.require(testScript);
while(nodeJS.isRunning()) {
nodeJS.handleMessage();
}
System.out.println(exports.contains("test"));
exports.release();
}
private static File createTemporaryScriptFile(final String script, final String name) throws IOException {
File tempFile = File.createTempFile(name, ".js.tmp");
PrintWriter writer = new PrintWriter(tempFile, "UTF-8");
try {
writer.print(script);
} finally {
writer.close();
}
return tempFile;
}
public void setAddress(String input) {
address = input;
}
I had some success by writing variables like this in the Javascript code:
global.myvar = "myval";

Using Rhino and JSR-223 to read a JSON file

I'm trying to read a JSON file with some JavaScript that I'm eval-ing with Rhino through the Java JSR-223 API. What I'm trying to do works with the Rhino shell, but not with the embedded Javascript in my Java code.
Here's what works:
$ java -jar js.jar
js> readFile('foo.json');
{y:"abc"}
Here is what does not work:
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("js");
engine.eval("readFile('foo.json')");
I get this error:
Exception in thread "main" javax.script.ScriptException:
sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "readFile" is not defined. (<Unknown source>#4) in <Unknown source> at line number 4
at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:153)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:232)
How can i get the readFile to be available in my engine?
If you are just trying to parse JSON, I would suggest using a JSON parsing library like Jackson or Jettison, it's a much easier approach. The readFile call returns a string, and it is not actually converting the contents into a JavaScript object. A JSON.parse or JavaScript eval call on the string would be needed in order to accomplish that.
If you really need to use the JavaScript engine to parse JSON and you were using Java 7 you could do something like this (but I wouldn't advise it)...
public static void main(final String args[]) throws Exception {
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("js");
Object val = null;
Scanner s = null;
try {
s = new Scanner(new File("foo.json"));
s.useDelimiter("\\Z");
engine.getBindings(ScriptContext.GLOBAL_SCOPE).put("json", s.next());
} finally {
if (s != null) {
s.close();
}
}
// The default JavaScript engine in Java 6 does not have JSON.parse
// but eval('(' + json + ')') would work
val = engine.eval("JSON.parse(json)");
// The default value is probably a JavaScript internal object and not very useful
System.out.println(val.getClass() + " = " + val);
// Java 7 uses Rhino 1.7R3 the objects will implement Map or List where appropriate
// So in Java 7 we can turn this into something a little more useable
// This is where Java 6 breaks down, in Java 6 you would have to use the
// sun.org.mozilla.javascript.internal classes to get any useful data
System.out.println(convert(val));
}
#SuppressWarnings("unchecked")
public static Object convert(final Object val) {
if (val instanceof Map) {
final Map<String, Object> result = new HashMap<String, Object>();
for (final Map.Entry<String, Object> entry: ((Map<String, Object>) val).entrySet()) {
result.put(entry.getKey(), convert(entry.getValue()));
}
return result;
} else if (val instanceof List) {
final List<Object> result = new ArrayList<Object>();
for (final Object item: ((List<Object>) val)) {
result.add(convert(item));
}
return result;
}
if (val != null) {
System.out.println(val.getClass() + " = " + val);
}
return val;
}
The JavaScript engine provided in Java has excluded some of the features provided in Rhino. The readFile function is actually provided by the Rhino Shell, not the engine implementation. Oracle also provides functions accessible by the jrunscript shell which are not in the engine.
Here's an example that mimics the Rhino shell readFile function and adds it to the JavaScript scope based upon the answer to this question:
How can I add methods from a Java class as global functions in Javascript using Rhino?
public static void main(final String args[]) throws Exception {
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("js");
engine.getBindings(ScriptContext.GLOBAL_SCOPE).put("utils", new Utils());
engine.eval("for(var fn in utils) {\r\n" +
" if(typeof utils[fn] === 'function') {\r\n" +
" this[fn] = (function() {\r\n" +
" var method = utils[fn];\r\n" +
" return function() {\r\n" +
" return method.apply(utils,arguments);\r\n" +
" };\r\n" +
" })();\r\n" +
" }\r\n" +
"}");
engine.eval("println(readFile('foo.json'))");
}
static class Utils {
public String readFile(final String fileName) throws FileNotFoundException {
return readFile(fileName, null);
}
public String readFile(final String fileName, final String encoding) throws FileNotFoundException {
Scanner s = null;
try {
s = new Scanner(new File(fileName), (encoding == null)? Charset.defaultCharset().name(): encoding);
s.useDelimiter("\\Z");
return s.next();
} finally {
if (s != null) {
s.close();
}
}
}
}
You can always just leverage the relevant Java classes to slurp in the JSON file, then decorate it so it's suitable for an eval().
It can be done neatly in one line. For example given the following:
cfg.json:
{
myopts: {
username: "tee",
password: "password"
}
}
And the following Javascript:
cfg = eval('(' + new java.util.Scanner( new java.io.File('cfg.json') ).useDelimiter("\\A").next() + ')');
You can now access your JSON in Javascript via:
log.info("Username: " + cfg.myopts.username ); // "Username: tee"

Categories

Resources