Following ONVIF documentation, the password digest for making ONVIF Soap request should be like this.
PasswordDigest = B64ENCODE( SHA1( B64DECODE( Nonce ) + Date + Password ) )
For example:
Nonce – LKqI6G/AikKCQrN0zqZFlg==
Date – 2010-09-16T07:50:45Z
Password – userpassword
Resulting Digest – tuOSpGlFlIXsozq4HFNeeGeFLEI=
Below is how I have written in C++, which resulted in an invalid user token.
std::string dateTime = "2022-09-10T10:10:59.000Z";
std::string nonce = "secret";
std::string password = "mypassword";
std::string str = decode_str(nonce) + dateTime + password;
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *) str.c_str(), strlen(str.c_str()) - 1, hash);
uint8_t * hash_ptr = hash;
std::string psswrd = encode_str(hash_ptr, sizeof(hash));
std::cout << psswrd << std::endl; // +cz8/SJS89Uee7cTjW9aiMG9CTE=
But the above password is invalid, resulted the request to fail after timeout.
How to create Password Digest for ONVIF in C++?
I believe your problem is in the call to SHA1. The second parameter (length of the string to be hashed) is strlen(str) - 1, meaning you cut off the final character of the password, which will then result in an invalid hash.
Please either use the length function of std::string or strlen without that decrement (which does not include the \0).
The second 'problem' is in the string nonce, which is not a Base64 string at all, however I am willing to assume this to be a plain 'example value' because you do not wish you disclose your actual nonce value.
Below is a valid digest password.
std::string dateTime = "2022-09-10T10:10:59.000Z";
std::string nonce = "secret";
std::string password = "mypassword";
std::string str = nonce + dateTime + password;
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *) str.c_str(), str.size(), hash);
uint8_t * hash_ptr = hash;
std::string psswrd = encode_str(hash_ptr, sizeof(hash));
Related
I'm writing some script for ESP32 and struggling to serialize a json.
Used libraries are HTTPClient and ArduinoJson.
String payload = http.getString();
Serial.println(payload);
deserializeJson(result, payload);
const char* usuario = result["user"];
Serial.println("##########");
Serial.println(usuario);
The received payload is:
{"ip":"10.57.39.137","area":"[{\"id\":\"3\",\"text\":\"BOX\"}]","user":"[{\"id\":\"6270\",\"text\":\"ANDRE LARA OLIVEIRA E SILVA\"}]","teamId":6,"id":4,"siteId":2,"userCreate":"100059527","dateCreate":"2020-11-19T08:49:03.957","userUpdate":null,"dateUpdate":null}
I need to retrieve id and text from "user" key. It's fine to deserialize and retrieve user object. But result["user"] returns: [{"id":"6270","text":"ANDRE LARA OLIVEIRA E SILVA"}] to the char array. So it's something like a json nested in an array... and it's not working out to deserialize.
Can anyone help me how to properly get the "id" and "text" values from "user" object?
The library doesn't know the content of that string is valid JSON, so you have re-parse it. This code worked for me on my PC, though I don't have an Arduino to test it on:
auto payload = "..."; // JSON content here
StaticJsonDocument<1024> result;
deserializeJson(result, payload);
auto user = result["user"].as<const char*>();
StaticJsonDocument<256> userObj;
deserializeJson(userObj, user);
auto id = userObj[0]["id"].as<int>();
auto text = userObj[0]["text"].as<const char*>();
"Can anyone help me how to properly get the "id" and "text" values from "user" object?" You can access them with
const char *id = result["user"]["id"];
const char *text = result["user"]["text"];
Try:
const int id = result["user"]["id"];
const char* text = result["user"]["text"];
I am trying to use the arduino-mqtt lib.
I have this working sending the json string. The problem comes with trying to parse the string with ArduinioJson. It just returns no value.
I think it may have todo with the pointer reference in the mqttMessageRecived function ( String &payload).
Function called when there is an MQTT message:
void mqttMessageReceived(String &topic, String &payload){
//Example String for test
String json = "{"id" : "100" , "cmd" : "0xff"}";
jsonout(payload);
Serial.println("Sending Static String");
jsonout(json);
Function to parse json input:
void jsonout(String Json){
StaticJsonDocument<200> doc;
//Deserialize the JSON document
DeserializationError error = deserializeJson(doc, Json);
Serial.println("Got String: ");
Serial.println(Json);
// Test if parsing succeeds.
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
const char* id = doc["id"];
const char* cmd = doc["cmd"];
// Print values.
Serial.println(id);
Serial.println(cmd);
}
Non parsed output:
Message from MQTT
Got String:
"{\"id\" : 4 , \"cmd\": \"0xee\"}"
Result = No output from json parse
Non parsed output:
Sending Static String
Got String:
{"id" : "100" , "cmd" : "0xff"}
Result = Output from json parse:
100
0xff
The problem is that - in the response from the server
"{\"id\" : 4 , \"cmd\": \"0xee\"}"
the id field is an integer - not a character array.
So you need to change
const char* id = doc["id"];
to
int id = doc["id"];
(and update your test string to use an int for the ID also).
The server returns a id member that's a Number "id":4, while you are generating a id that's a String "id":"200".
You need to adjust your code to either one. If it's a number (and it seems so), you need to send "id":200 and change your code to get a number:
unsigned id = (double)doc["id"];
// And to generate it:
String json = "{\"id\" : 100 , \"cmd\" : \"0xff\"}";
Also, with JSON, beware of hexadecimal encoding, has it's not converted to number (you have to do it yourself by receiving a const char* and calling sscanf or strtol or ...) and it's not convenient. It's better to use base-10 encoding instead:
String json = "{\"id\" : 100 , \"cmd\" : 255}";
i have setup a working mysql connector for my c++ project. Now i'm making a login for registered users.
i want to get the username and password into the SQLquery string.
i am trying to get this working:
currently its displaying noting and the game crashes.
#include "boost/lexical_cast.hpp" //boost
#include <cgl\cgl.h> // game library (core media library)
#include <sstream> // sstream
char* username=DEFSER;
char* password=PASS12345;
const char *SQLquery;
std::string SQLquery("SELECT * FROM Users WHERE UserName='" + boost::lexical_cast<std::string>(username) + "' AND PassWord='" + boost::lexical_cast<std::string>(password) + "'");
what i want to get out of SQLquery:
SELECT * FROM Users WHERE UserName='DEFSER' AND PassWord='PASS12345'
and i execute it in this way:
res = stmt->executeQuery(SQLquery);
this is not a fully working code i only want to know how i can get the username and password into the SQLquery.
error when i try to run the query:
Run-Time Check Failure #3 - The variable 'SQLquery' is being used without being initialized.
What you are doing is not concatenating strings, you are adding std::string objects to a literal string pointer.
The std::string class handles concatenation of C-style strings just fine without any lexical_cast, so just do e.g.
std::string SQLquery = "SELECT * FROM Users WHERE UserName='" +
username + "' AND PassWord='" + password + "'";
After testing the above solution doesn't actually work for me. But the following does:
std::string SQLQuery = (std::ostringstream() << "SELECT * FROM Users WHERE UserName='"
<< username << "' AND PassWord='" << password << "'").str();
Can anyone help me to upload image to azure storage using qt/c++
here's my code. it seems to have an error on constructing the headers.*
QByteArray data;
QFile file("Bg.jpg");
if (file.open(QIODevice::ReadOnly))
{
data.append(file.readAll()); //let's read the file
}
QString date = QDateTime::currentDateTime().toString("ddd, d MMM yyyy HH:mm:ss") + " GMT";
QString header = QString("PUT\n\n\n%1\n\n\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:%2\nx-ms-version:2013-08-15\n/mycontainer/todate/").arg(data.length()).arg(date);
QString urlUri = "http://myaccount.blob.core.windows.net/mycontainer/todate";
QByteArray ba = header.toUtf8();
unsigned char* signature = reinterpret_cast<unsigned char*>(ba.data());
QByteArray kba =
QByteArray::fromBase64("key");
unsigned char* key = (unsigned char*) kba.data();
unsigned char result[EVP_MAX_MD_SIZE];
unsigned int result_len;
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, key, strlen((const char*)key), EVP_sha256(), NULL);
HMAC_Update(&ctx, signature, strlen((const char*)signature));
HMAC_Final(&ctx, result, &result_len);
HMAC_CTX_cleanup(&ctx);
QByteArray array = QByteArray::fromRawData((char*)result, result_len);
array = array.toBase64();
String version = "2013-08-15";
QNetworkAccessManager* manager = new QNetworkAccessManager();
QNetworkRequest request;
request.setUrl(QUrl(urlUri));
request.setRawHeader("Content- Length",QString::number(data.length()).toStdString().c_str());
request.setRawHeader("Content-Type","application/octet-stream");
request.setRawHeader("x-ms-blob-type","BlockBlob");
request.setRawHeader("x-ms-date", date.toStdString().c_str());
request.setRawHeader("x-ms-version", version.toStdString().c_str());
request.setRawHeader("Authorization","SharedKey myaccount:"+array);
manager->post(request,data);
connect(manager, SIGNAL(finished(QNetworkReply*)), this,SLOT(manageCloudReply(QNetworkReply*)));
and this is the response on the request
AuthenticationFailed Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:82eb03cb-adf1-4797-bbc0-86c3e5ca3ec6
Time:2014-03-19T03:52:35.4790761ZThe MAC signature found in the HTTP request '3Dk7laN3XW+ASbQj0XddfmSnnuYfVSkhg/oRfSJekKY=' is not the same as any computed signature. Server used following string to sign: 'POST
87163
application/octet-stream
x-ms-blob-type:BlockBlob
x-ms-date:Wed, 19 Mar 2014 11:52:05 GMT
x-ms-version:2013-08-15
/logboxstorage/mycontainer/todate'.
any help will be appreciated..thanks!!!!
Looking at the following line of code:
QString header = QString("PUT\n\n\n%1\n\n\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:%2\nx-ms-version:2013-08-15\n/mycontainer/todate/").arg(data.length()).arg(date);
I see an extra slash (/) in mycontainer/todate/. Can you try by removing that?
Also look at the following code:
QString date = QDateTime::currentDateTime().toString("ddd, d MMM yyyy HH:mm:ss") + " GMT";
currentDateTime() will return the local date/time based on your computer. It should be UTC/GMT date/time. Try using currentDateTimeUtc().
Another thing I noticed is that your request is going as POST to the server. It should be a PUT request.
Hmm, for some reason, its only doing this on the first username (and password) and does it for how big my my vector is. Any ideas on why?
int eMysql::strip(string &input) {
char* from = new char[strlen(input.c_str()) * 3 + 1];
mysql_real_escape_string(&mysql, from, input.c_str(), input.length());
input = input.assign(from);
delete from;
}
Where its used:
if(query.size() > 0) {
mysql->strip(query[0]);
mysql->strip(query[1]);
mysql->query("SELECT `username` FROM `users` where `username` = '"+ query[0] +"';");
I suggest building the query as a separate string variable rather than passing the mess in the argument:
static const char fixed_text[] = "SELECT `username` FROM `users` where `username` = '";
std::string query_text(fixed_text);
query_text += query[0];
query_text += "';";
mysql->query(query_text);
This technique allows you to examine the query before it is sent to MySql.
I suggest you examine the query[0] variable for any strange characters such as \r and \n. The MySql manual has a section listing characters that need to be escaped.