Using setWebhook from Qt for a Telegram bot - qt

Im developing a Telegram bot using Qt c++, and i'm having problems trying to set a Webhook.
SSL Server
First of all, i've created a ssl server using QTcpServer and QSslSocket. Some explanations about this can be found in the QSslSocket doc. Also, i generated a self-signed certificate as Telegram doc explains here, using the command:
openssl req -newkey rsa:2048 -sha256 -nodes -keyout YOURPRIVATE.key -x509 -days 365 -out YOURPUBLIC.pem -subj "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=YOURDOMAIN.EXAMPLE"
The result is a pair of files, a private.key file and a public.pem file. So, i used them in the QSslSockets to secure the connection.
The result of that is a ssl server capable of listen and accept connections. When i use a browser to connect to my ssl server, i obtain a warning about using a self-signed certificate (which i think is normal), but can connect to the server. From the server, i'm able of read the data that browser sent. So, i think the server side is good.
Request for setWebhook
In order to perform a request for setWebhook API method, i use QHttpMultipart class to create a MIME Multipart request. The API method needs the Url to be contacted and the public certificate. So, i use this code to generate the url parameter:
QList<QHttpPart> parameters;
QHttpPart urlPart;
urlPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
urlPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"url\""));
urlPart.setBody(_url.toLatin1());
parameters.append(urlPart);
And this code to generate the certificate parameter:
QHttpPart filePath;
filePath.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"certificate\""));
QFile *file = new QFile(_filePath);
file->open(QIODevice::ReadOnly);
filePath.setBodyDevice(file);
file->setParent(this);
parameters.append(filePath);
I receive a correct response, with the message that "the webhook was set". But, when Telegram connects to my ssl server, the ssl handshake doesn't finish in a right way (neither encrypted() nor sslError() signals are emitted). I think that the problem is the way i upload the public certificate. As you can see, for the file QHttpPart, i doesn't set the content-type header because i don't know what value to use. I don't know if this can be the problem. I use "text/plain" for url, but don't know what to use for the certificate file.
So, i don't know what could be my problem. Even, i'm not sure if it could be the file upload or not. Using a self signed certificate is not a problem, since the documentation indicates this as a valid way. Any help would be appreciated.
Thanks in advance.

I finally found the problem, and it was the content-type. I removed the content-type of the first param, the urlPart. And also added the content-type to the filePath, using as value "application/x-x509-ca-cert". It works like a charm now.

Related

Is there a way to set the http Header values for an esp_https_ota call?

I'm trying to download a firmware.bin file that is produced in a private Github repository. I have the code that is finding the right asset url to download the file and per Github instructions the accept header needs to be set to accept: application/octet-stream in order to get the binary file. I'm only getting JSON in response. If I run the same request through postman I'm getting a binary file as the body. I've tried downloading it using HTTPClient and I get the same JSON request. It seems the headers aren't being set as requested to tell Github to send the binary content as I'm just getting JSON. As for the ArduinoOTA abstraction, I can't see how to even try to set headers and in digging into the esp_https_ota functions and http_client functions there doesn't appear to be a way to set headers for any of these higher level abstractions because the http_config object has no place for headers as far as I can tell. I might file a feature request to allow for this, but am new to this programming area and want to check to see if I'm missing something first.
Code returns JSON, not binary. URL is github rest api url to the asset (works in postman)
HTTPClient http2;
http2.setAuthorization(githubname,githubpass);
http2.addHeader("Authorization","token MYTOKEN");
http2.addHeader("accept","application/octet-stream");
http2.begin( firmwareURL, GHAPI_CERT); //Specify the URL and certificate
With the ESP IDF HTTP client you can add headers to an initialized HTTP client using function esp_http_client_set_header().
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_header(client, "HeaderKey", "HeaderValue");
err = esp_http_client_perform(client);
If using the HTTPS OTA API, you can register for a callback which gives you a handle to the underlying HTTP client. You can then do the exact same as in above example.

cannot connecting Microsoft Flows with HTTP request using certificate authentification

I am a new user for Microsoft Flows.
I have a requirement for Connecting the Microsoft Flow with HTTP Request.
When connecting the HTTP Request, I am using the Client Certificate with the .pfx certificate file.
I am using the below format :
{ "type": "ClientCertificate", "pfx": "aGVsbG8g...d29ybGQ=", "password": "myPassword" }
I am adding the pfx file in Base64 Encoding Format and Password in Plain Text format.
While running the Flow, I get the below error :
BadRequest. Unable to load the certificate private key. Please check that the password of the authentication certificate is correct, then try again.
Thanks, :)
I have had a similar experience, but the solution here is simple: The error message is right, either you have the wrong or incomplete base64 certificate string (copy-paste errors happen) or you have the wrong password to the certificate. There really is nothing more to it, the JSON form looks fine.

How to get digital signature of the request (in two-way SSL)?

In an ASP.Net web app, which runs on HTTPS and has RequireClientCertificate set in web.config, I need to receive the client certificate of the user and digital signature of the request on the server. The certificate is found in HttpContext.Request.ClientCertificate, but I can't find the signed data. The post params are automatically decoded and decrypted, but I need the signature too. Does anyone know where is it found or is it possible to get it?
One more question, when the browser asks for your certificate and hands it to the server, does it encrypt the whole HttpRequest with your private key or just a part of it (for example post params)?
Thanks for any help
One more question, when the browser asks for your certificate and
hands it to the server, does it encrypt the whole HttpRequest with
your private key or just a part of it (for example post params)?
Firstly, it doesn't make sense to "encrypt with a private key": you sign with a private key. While some algorithms (e.g. RSA) use very similar procedures to encrypt and sign, "encrypt" means "hiding" something: you're not hiding anything if anyone with the public key can decipher it.
Secondly, SSL/TLS uses symmetric keys (negotiated during the handshake) for encryption, not the keys in the certificates. The whole HTTP request will indeed be encrypted in this case.
The certificate is found in HttpContext.Request.ClientCertificate, but
I can't find the signed data. The post params are automatically
decoded and decrypted, but I need the signature too. Does anyone know
where is it found or is it possible to get it?
What's signed when using a client certificate is the handshake messages, not the HTTP request. Once the appropriate verification has been made by your SSL/TLS stack, it's unlikely to be of any use, either technically or administratively. (This is why it is generally not accessible.)

how a password is sent in HTTP protocol?

am sorry for this dumb question, but am using RawCap to detect packets sent and received to learn what is sent in HTTP, and the page is a simple application made using Tornado and MongoDB, when i capture packets, i dont find the password in any packet sent.
Why? i dont use any encrypted protocole like HTTPS, it's a simple HTTP and cant see the password.
here is the file:
The result
as you can see, Mongodb answers the value of the database, and brings the password as it is saved (PBKDF2), but cant see the one sent from the first time.
Most likely, you don't see the password because the page is using HTTP basic authentication which encodes the username and password using base64. Look for a string like:
Authorization: SomeRealmName QWxhZGRpbjpvcGVuIHNlc2FtZQ==
If you're using Basic authentication, then the password is base 64 encoded. ENCODED not encrypted. Look for something like this in your packets: Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

I keep receiving "invalid-site-private-key" on my reCAPTCHA validation request

maybe you guys can help me with this. I am trying to implement
reCAPTCHA in my node.js application and no matter what I do, I keep
getting "invalid-site-private-key" as a response.
Here are the things I double and double checked and tried:
Correct Keys
Keys are not swapped
Keys are "global keys" as I am testing on localhost and thought it might be an issue with that
Tested in production environment on the server - same problem
The last thing I can think of is that my POST request to the reCAPTCHA
API itself is incorrect as the concrete format of the body is not
explicitly documented (the parameters are documented, I know). So this
is the request body I am currently sending (the key and IP is changed
but I checked them on my side):
privatekey=6LcHN8gSAABAAEt_gKsSwfuSfsam9ebhPJa8w_EV&remoteip=10.92.165.132& challenge=03AHJ_Vuu85MroKzagMlXq_trMemw4hKSP648MOf1JCua9W-5R968i2pPjE0jjDGX TYmWNjaqUXTGJOyMO3IKKOGtkeg_Xnn2UVAfoXHVQ-0VCHYPNwrj3PQgGj22EFv7RGSsuNfJCyn mwTO8TnwZZMRjHFrsglar2zQ&response=Coleshill areacce
Is there something wrong with this format? Do I have to send special
headers? Am I completely wrong? (I am working for 16 hours straight
now so this might be ..)
Thank you for your help!
As stated in the comments above, I was able to solve the problem myself with the help of broofa and the node-recaptcha module available at https://github.com/mirhampt/node-recaptcha.
But first, to complete the missing details from above:
I didn't use any module, my solution is completely self-written based on the documentation available at the reCAPTCHA website.
I didn't send any request headers as there was nothing stated in the documentation. Everything that is said concerning the request before they explain the necessary parameters is the following:
"After your page is successfully displaying reCAPTCHA, you need to configure your form to check whether the answers entered by the users are correct. This is achieved by doing a POST request to http://www.google.com/recaptcha/api/verify. Below are the relevant parameters."
-- "How to Check the User's Answer" at http://code.google.com/apis/recaptcha/docs/verify.html
So I built a querystring myself (which is a one-liner but there is a module for that as well as I learned now) containing all parameters and sent it to the reCAPTCHA API endpoint. All I received was the error code invalid-site-private-key, which actually (as we know by now) is a wrong way of really sending a 400 Bad Request. Maybe they should think about implementing this then people would not wonder what's wrong with their keys.
These are the header parameters which are obviously necessary (they imply you're sending a form):
Content-Length which has to be the length of the query string
Content-Type which has to be application/x-www-form-urlencoded
Another thing I learned from the node-recaptcha module is, that one should send the querystring utf8 encoded.
My solution now looks like this, you may use it or built up on it but error handling is not implemented yet. And it's written in CoffeeScript.
http = require 'http'
module.exports.check = (remoteip, challenge, response, callback) ->
privatekey = 'placeyourprivatekeyhere'
request_body = "privatekey=#{privatekey}&remoteip=#{remoteip}&challenge=#{challenge}&response=#{response}"
response_body = ''
options =
host: 'www.google.com'
port: 80
method: 'POST'
path: '/recaptcha/api/verify'
req = http.request options, (res) ->
res.setEncoding 'utf8'
res.on 'data', (chunk) ->
response_body += chunk
res.on 'end', () ->
callback response_body.substring(0,4) == 'true'
req.setHeader 'Content-Length', request_body.length
req.setHeader 'Content-Type', 'application/x-www-form-urlencoded'
req.write request_body, 'utf8'
req.end()
Thank you :)
+1 to #florian for the very helpful answer. For posterity, I thought I'd provide some information about how to verify what your captcha request looks like to help you make sure that the appropriate headers and parameters are being specified.
If you are on a Mac or a Linux machine or have access to one of these locally, you can use the netcat command to setup a quick server. I guess there are netcat windows ports but I have no experience with them.
nc -l 8100
This command creates a TCP socket listening on pot 8100 and will wait for a connection. You then can change the captcha verify URL from http://www.google.com/recaptcha/... in your server code to be http://localhost:8100/. When your code makes the POST to the verify URL you should see your request outputted to the scree by netcat:
POST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 277
Host: localhost:8100
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1 (java 1.5)
privatekey=XXX&remoteip=127.0.0.1&challenge=03AHJYYY...&response=some+words
Using this, I was able to see that my private-key was corrupted.

Resources