Python App Emulator

That web page indicates that your (self-signed) certificate NEEDS the X509v3 Subject ALternative Name to be set to your DNS name of your host. For example mine has:

X509v3 Subject Alternative Name: 
        DNS:iot.<redacted>.net, DNS:iot.<redacted>.<redacted>.net

I have two URLs as one works inside my house only while the other is global

And here is the certificate for blynk-cloud.com

Data:
    Version: 3 (0x2)
    Serial Number:
        81:d2:9d:bf:9c:bf:81:02
    Signature Algorithm: sha256WithRSAEncryption
    Issuer: C = UA, ST = Kyiv, L = Kyiv, O = IT, OU = Blynk Inc., CN = blynk-cloud.com, emailAddress = dmitriy@blynk.cc
    Validity
        Not Before: Mar 17 11:58:07 2016 GMT
        Not After : Mar 16 11:58:07 2021 GMT
    Subject: C = UA, ST = Kyiv, L = Kyiv, O = IT, OU = Blynk Inc., CN = blynk-cloud.com, emailAddress = dmitriy@blynk.cc
    Subject Public Key Info:
        Public Key Algorithm: rsaEncryption
            RSA Public-Key: (2048 bit)
            Modulus:
                00:bb:28:6e:16:d7:42:e3:65:cd:80:45:6b:d8:7d:
                a5:de:bd:9f:8d:f2:ac:64:cb:e0:16:ba:93:94:35:
                cc:3c:18:f4:74:1b:31:d7:c2:e5:97:e7:0a:4a:93:
                ed:97:fe:47:93:0e:45:6d:10:f6:72:ec:14:d2:c9:
                93:02:a7:96:e4:42:60:6c:94:11:2f:0d:02:60:cb:
                40:16:d9:a1:57:3c:9a:ff:4a:de:62:20:01:0b:c6:
                c9:8d:8b:98:a6:a4:e4:64:88:57:43:c2:df:1f:a2:
                37:4d:f1:53:6e:fb:e3:e6:62:ec:36:90:77:bb:d3:
                97:ff:51:1a:4f:0c:73:21:de:fe:ce:48:91:b7:b5:
                e1:bc:d6:71:8f:59:57:83:ca:80:27:24:a7:57:21:
                6e:62:e1:49:f1:9b:4f:7b:fa:e2:c2:fc:65:b2:29:
                a5:09:39:ef:f2:60:b1:93:2b:56:98:c4:c6:fc:50:
                3d:9b:89:7d:66:ed:a3:2a:4f:7e:96:0e:f8:ef:25:
                d6:cc:da:32:54:c4:3c:86:55:32:86:22:f6:e1:3e:
                0e:73:a5:87:32:45:9f:a0:1c:e0:53:2b:0f:32:57:
                cc:c9:82:c1:e4:97:dc:8c:60:ba:f5:c0:2d:e2:a1:
                50:74:09:f9:53:f7:1b:a4:37:a6:46:51:54:ac:fe:
                e5:7b
            Exponent: 65537 (0x10001)
    X509v3 extensions:
        X509v3 Subject Key Identifier: 
            9B:6A:B4:8E:B6:22:8E:BA:71:98:22:4D:1E:4B:03:94:E5:E6:6F:B1
        X509v3 Authority Key Identifier: 
            keyid:9B:6A:B4:8E:B6:22:8E:BA:71:98:22:4D:1E:4B:03:94:E5:E6:6F:B1

        X509v3 Basic Constraints: 
            CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
     aa:61:8e:d1:0e:1a:ce:e8:0b:74:bc:ef:e0:14:80:8c:38:80:
     53:4e:ba:ff:8b:0b:df:3f:97:8e:ce:0f:a5:ad:b2:a2:4a:bc:
     26:75:96:62:b1:63:96:88:ae:8f:45:04:f9:3c:92:d0:8e:b1:
     bc:04:8c:4f:a7:ca:be:70:ba:5f:ba:08:b1:6b:fa:b9:ef:ec:
     e1:d8:1b:02:e9:8e:8c:fe:ad:98:18:26:24:3a:d4:4d:66:d0:
     06:78:cb:d1:72:77:e0:fd:d0:75:ba:db:8e:ef:ac:15:f2:12:
     25:17:3a:13:7f:a0:30:d5:7c:34:00:7a:a9:8d:07:1d:4e:a9:
     67:a5:f3:50:f7:b4:0e:f3:3c:c0:3b:bd:42:2d:c9:67:05:21:
     73:63:38:23:fe:3c:ec:bb:4c:cc:59:ba:1b:8f:32:1e:5b:56:
     ef:bf:72:d8:65:fd:0f:6e:fd:9d:a5:2a:5e:02:59:5d:08:be:
     dd:81:b6:53:7a:89:e7:ef:6b:47:b6:00:ff:c0:b3:e8:1f:c2:
     3c:6b:6f:4b:75:d7:34:88:2c:b3:49:fa:7c:51:23:08:3e:93:
     83:06:6f:5c:e2:84:a6:c8:5d:4c:ec:8e:c9:4e:34:ae:05:63:
     9a:e5:41:44:b0:28:98:04:01:51:74:0a:5c:41:e2:0e:9d:10:
     29:b4:72:47

This is a simple self-signed certificate

I get this…

2021-06-14 00:38:56,450 [INFO]  Connecting to blynk-cloud.com:443
2021-06-14 00:38:56,592 [INFO]  Using SSL socket...
2021-06-14 00:38:56,630 [ERROR]  Connection with the Blynk server failed: Cannot set verify_mode to CERT_NONE when check_hostname is enabled.

I haven’t found this check_hostname reference in your files yet.

Well, I took that file and cleverly named it cert_chain.crt dumped it in the same folder as your python ones and ran this…

return {'server': 'blynk-cloud.com', 'port': 443, 'ssl': True, 'certificate': './cert_chain.crt'}

and got back something slightly different… progress??

2021-06-14 00:49:33,165 [INFO]  Connecting to blynk-cloud.com:443
2021-06-14 00:49:44,407 [INFO]  Using SSL socket...
2021-06-14 00:49:44,423 [ERROR]  Connection with the Blynk server failed: [X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4293)

I note that the blynk-cloud certificate has also expired :slight_smile:

I just tried to use the downloaded certificate to connect there and it failed with

2021-06-14 17:51:22,654 [INFO]  Using SSL socket...
2021-06-14 17:51:22,901 [ERROR]  Connection with the Blynk server failed: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1145)

And that is true if you look at my previous post

I changed to ssl.CERT_NONE and got the same error, add the following line immediately above the line that sets verify_mode

ssl_context.check_hostname = False

Strange, when I try to login to blynk-cloud with incorrect credentials, nothing happens, yet when I login in to my local server with incorrect credentials, I get an authentication error message immediately

spaces vs tabs… arggg… oh well, that was my whole purpose of going down this rabbit hole, to learn more how Python works by following more and more complex examples.

But this certification thing has me thinking I ended up down the wrong-end-of-the-rabbit hole instead :laughing:

Using the cloud server and your edits…

return {'server': 'blynk-cloud.com', 'port': 443, 'ssl': True}
ssl_context.check_hostname = False ## Added to test following line
ssl_context.verify_mode = ssl.CERT_NONE ##ssl.CERT_REQUIRED

and got this…

2021-06-14 00:58:51,662 [DEBUG]  Request(server details)
2021-06-14 00:58:51,669 [INFO]  Connecting to blynk-cloud.com:443
2021-06-14 00:58:51,857 [INFO]  Using SSL socket...
2021-06-14 00:58:52,126 [INFO]  Connection to Blynk server established
2021-06-14 00:58:52,172 [DEBUG]  Request(auth details)
2021-06-14 00:58:52,180 [INFO]  Authenticating user: <REDACTED>@gmail.com
2021-06-14 00:58:52,190 [DEBUG]  Sending BlynkLoginMessage - BlynkCommand(Login) ID(1): ['<REDACTED>@gmail.com', 'VyD3Yy0nyzln6bbEyTd3zuLdbxmmceUIamalM6WKjxU=', 'Python App', '0.2.6_app', 'Blynk']
Traceback (most recent call last):
  File "C:\Users\Gunner\blynk_app_demo\blynk_app.py", line 216, in <module>
    main()
  File "C:\Users\Gunner\blynk_app_demo\blynk_app.py", line 213, in main
    timer.run()
  File "C:\Users\Gunner\blynk_app_demo\blynktimer.py", line 102, in run
    timers_intervals = [curr_timer.run() for curr_timer in Timer.timers.values() if not curr_timer.stopped]
  File "C:\Users\Gunner\blynk_app_demo\blynktimer.py", line 102, in <listcomp>
    timers_intervals = [curr_timer.run() for curr_timer in Timer.timers.values() if not curr_timer.stopped]
  File "C:\Users\Gunner\blynk_app_demo\blynktimer.py", line 127, in run
    self.deco(*self.args, **self.kwargs)
  File "C:\Users\Gunner\blynk_app_demo\blynk_app.py", line 199, in toggle_door_button
    blynkapp['widgets']['button']['value'] = int(blynkapp['widgets']['button']['value']) + 1
KeyError: 'value'

Looks familiar to what I was first seeing at the beginning of this topic… arrg.

Yes I found this and fixed this, the socket read timeout is too short for talking to the cloud instead of the local server, and the authentication cycle does not happen in a loop. A temporary fix is to change the value of SOCK_TIMEOUT (line 120) to 1 (1 second) instead of 0.05 seconds

In the meantime I’ll try to think of a cleaner approach here

Also, if you add

if not blynk.connected(): return

To the timer callback function that toggles the button widget, the program will at least not crash :slight_smile:

Do you guys realise that you can no longer use SSL with the Blynk cloud servers?

Pete.

@PeteKnight apparently you can if you connect without authenticating the certificate (as it has expired)

I jsut did and the authentication failed

Sounds like something that changed during the last year+ when I stopped using Blynk altogether :blush: Darn, forgot to RTFM :laughing:

So @Gunner now that you can connect with verification set to NONE, can you try the local server again?

Pete.

Set the socket timeout back to 0.05 and replace the line:

response = BlynkMessage.ReadSocketMessage(self.__recv_bytes)

in the __authenticate method with:

for attempt in range(20):
        try:
            response = BlynkMessage.ReadSocketMessage(self.__recv_bytes)
            break
        except BlynkTimeoutError:
            pass

Don’t forget to check the indentation
This will keep the timeout at 0.05 seconds and loop up to 20 times waiting for an authentication response from the Blynk server

THanks for that, that would be due to the certificate expiring earlier this year

Validity
        Not Before: Mar 17 11:58:07 2016 GMT
        Not After : Mar 16 11:58:07 2021 GMT

But connecting with no certification required and no checking for host name allows the world to keep on going

@PeteKnight

So does that only impact devices connecting to the cloud using SSL or the mobile phone app as well?

OK, I think I go this done.

And I think I found the function… but where to add?

# Called every 30 seconds to request the server to send the push or release the button widget in the dashboard
@timer.register(interval=30, run_once=False)
def toggle_door_button():
    """Toggle the current value (in blynkapp['widgets']['button']['value']) between 1 and 0 and then write that value to the dashboard"""
    global blynkapp

    blynkapp['widgets']['button']['value'] = int(blynkapp['widgets']['button']['value']) + 1
    if blynkapp['widgets']['button']['value'] >= 2: blynkapp['widgets']['button']['value'] = 0

    blynk.virtual_write('{}-{}'.format(blynkapp['id'], blynkapp['widgets']['button']['device']),
                        blynkapp['widgets']['button']['pin'], blynkapp['widgets']['button']['value'])

Right under the “global blynkapp” line

As a Python neophyte I have no idea what “lead cap” is… but I can almost understand the word “Global” :stuck_out_tongue:
So, like this?..

    global blynkapp
    if not blynk.connected(): return