Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smart Keypad - ValueError: invalid padding length byte #438

Open
mrbrdo opened this issue Dec 19, 2023 · 14 comments
Open

Smart Keypad - ValueError: invalid padding length byte #438

mrbrdo opened this issue Dec 19, 2023 · 14 comments
Labels
tuya_device Support for specific Tuya Devices

Comments

@mrbrdo
Copy link

mrbrdo commented Dec 19, 2023

I am interested in trying to add support for a Smart Keypad/Card+PIN device (product id s7qamihym60z5jro). I am aware it's not supported at this time. Would like to get some help with getting basic status / protocol / message encryption working and then I might be able to implement the functionality myself. When trying to do status(), I get the following error: ValueError: invalid padding length byte. How could I successfully decode the message?

Here is the debug output:

DEBUG:status() entry (dev_type is default)
DEBUG:final payload_dict for 'MYDEVID' ('v3.3'/'default'): {1: {'command': {'gwId': '', 'devId': '', 'uid': '', 't': ''}}, 7: {'command': {'devId': '', 'uid': '', 't': ''}}, 8: {'command': {'gwId': '', 'devId': ''}}, 9: {'command': {'gwId': '', 'devId': ''}}, 10: {'command': {'gwId': '', 'devId': '', 'uid': '', 't': ''}}, 13: {'command': {'devId': '', 'uid': '', 't': ''}}, 16: {'command': {'devId': '', 'uid': '', 't': ''}}, 18: {'command': {'dpId': [18, 19, 20]}}, 64: {'command': {'reqType': '', 'data': {}}}}
DEBUG:building command 10 payload=b'{"gwId":"MYDEVID","devId":"MYDEVID","uid":"MYDEVID","t":"1702944031"}'
DEBUG:sending payload
DEBUG:payload encrypted=b'000055aa000000010000000a00000088426805b5e7556886e67a7652b5bfa0d5585c80e7e213a9fd044ca73a85b24cc9ceb82602f298e8d2284261a322a03cd23630dd9c551b275eba920a8a288e19d7f1cc30c74556c9da6e69bfbde5341fc0585c80e7e213a9fd044ca73a85b24cc92a8dd8946f6c90dcd4faff0b1e79b606fd15c744626b1b2eff4deedbffcdf03b759660d70000aa55'
DEBUG:received data=b'000055aa000000010000000a0000002c00000001ddc430e4f6cb4f63398bbc4de08374c7e3891724694edf79f47e09dbaf36eb5ac9412c390000aa55'
DEBUG:received message=TuyaMessage(seqno=1, cmd=10, retcode=1, payload=b'\xdd\xc40\xe4\xf6\xcbOc9\x8b\xbcM\xe0\x83t\xc7\xe3\x89\x17$iN\xdfy\xf4~\t\xdb\xaf6\xebZ', crc=3376491577, crc_good=True, prefix=21930, iv=None)
DEBUG:raw unpacked message = TuyaMessage(seqno=1, cmd=10, retcode=1, payload=b'\xdd\xc40\xe4\xf6\xcbOc9\x8b\xbcM\xe0\x83t\xc7\xe3\x89\x17$iN\xdfy\xf4~\t\xdb\xaf6\xebZ', crc=3376491577, crc_good=True, prefix=21930, iv=None)
DEBUG:decode payload=b'\xdd\xc40\xe4\xf6\xcbOc9\x8b\xbcM\xe0\x83t\xc7\xe3\x89\x17$iN\xdfy\xf4~\t\xdb\xaf6\xebZ'
DEBUG:decrypting=b'\xdd\xc40\xe4\xf6\xcbOc9\x8b\xbcM\xe0\x83t\xc7\xe3\x89\x17$iN\xdfy\xf4~\t\xdb\xaf6\xebZ'
DEBUG:incomplete payload=b'\xdd\xc40\xe4\xf6\xcbOc9\x8b\xbcM\xe0\x83t\xc7\xe3\x89\x17$iN\xdfy\xf4~\t\xdb\xaf6\xebZ' (len:32)
Traceback (most recent call last):
  File "tinytuya/core.py", line 1386, in _decode_payload
    payload = cipher.decrypt(payload, False)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "tinytuya/core.py", line 325, in decrypt
    raw = self._unpad(raw, verify_padding)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "tinytuya/core.py", line 286, in _unpad
    raise ValueError("invalid padding length byte")
ValueError: invalid padding length byte
DEBUG:ERROR Unexpected Payload from Device - 904 - payload: null
DEBUG:status() received data={'Error': 'Unexpected Payload from Device', 'Err': '904', 'Payload': None}
DEBUG:Status request returned an error, is version 3.3 and local key b'MYLOCALKEY' correct?
set_status() result {'Error': 'Unexpected Payload from Device', 'Err': '904', 'Payload': None}

I'm happy to run any further commands and share more debug output.

@uzlonewolf
Copy link
Collaborator

That means it can't decrypt the response because the local key is wrong. I'd run the wizard again to make sure you have the latest key.

@mrbrdo
Copy link
Author

mrbrdo commented Dec 19, 2023

@uzlonewolf thanks, that fixed it, however I obtained the key several times before through the Tuya IoT API, and that one seems to be in a different format? This one from tinytuya seems like HEX format, but the one from the API definitely isn't in HEX.
Do you think there is any chance of using this device from tinytuya at the moment? For example unlock function and temporary code function.

{
  "result": {
    "category": "mk",
    "functions": [
      {
        "code": "unlock_method_create",
        "desc": "{}",
        "name": "添加开门方式",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_method_delete",
        "desc": "{}",
        "name": "删除开门方式",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_method_modify",
        "desc": "{}",
        "name": "修改开门方式",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "synch_method",
        "desc": "{}",
        "name": "同步开门方式(全量同步)",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "temporary_password_creat",
        "desc": "{}",
        "name": "添加临时密码",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "temporary_password_delete",
        "desc": "{}",
        "name": "删除临时密码",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "temporary_password_modify",
        "desc": "{}",
        "name": "修改临时密码",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "remote_no_pd_setkey",
        "desc": "{}",
        "name": "设置免密远程开门密钥",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "remote_no_dp_key",
        "desc": "{}",
        "name": "新免密远程开门-带密钥",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_password_kit",
        "desc": "{}",
        "name": "普通密码开门记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_card_kit",
        "desc": "{}",
        "name": "卡片开门记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_temporary_kit",
        "desc": "{}",
        "name": "临时密码开门记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_phone_remote_kit",
        "desc": "{}",
        "name": "手机远程开门记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "lock_alarm_kit",
        "desc": "{}",
        "name": "告警记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "closed_opened_kit",
        "desc": "{}",
        "name": "开合状态",
        "type": "Raw",
        "values": "{}"
      }
    ],
    "status": [
      {
        "code": "unlock_method_create",
        "name": "添加开门方式",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_method_delete",
        "name": "删除开门方式",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_method_modify",
        "name": "修改开门方式",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "synch_method",
        "name": "同步开门方式(全量同步)",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "temporary_password_creat",
        "name": "添加临时密码",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "temporary_password_delete",
        "name": "删除临时密码",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "temporary_password_modify",
        "name": "修改临时密码",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "remote_no_pd_setkey",
        "name": "设置免密远程开门密钥",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "remote_no_dp_key",
        "name": "新免密远程开门-带密钥",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_password_kit",
        "name": "普通密码开门记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_card_kit",
        "name": "卡片开门记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_temporary_kit",
        "name": "临时密码开门记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_offline_pd",
        "name": "离线密码解锁上报",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "unlock_phone_remote_kit",
        "name": "手机远程开门记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "lock_alarm_kit",
        "name": "告警记录",
        "type": "Raw",
        "values": "{}"
      },
      {
        "code": "closed_opened_kit",
        "name": "开合状态",
        "type": "Raw",
        "values": "{}"
      }
    ]
  },
  "success": true,
  "t": 1702990556281,
  "tid": "f31b297b9e6d11ee84c63652eadeec7d"
}

@uzlonewolf
Copy link
Collaborator

uzlonewolf commented Dec 19, 2023

I'm not sure what you mean about the key being encoded. Older keys were hexadecimal strings - they're not encoded, the key just consists of 0-9 and a-f characters. Newer ones use random symbols in addition to the full a-z/A-Z/0-9 character set. I have no idea what IoT API you used so I'm not sure what data it's returning; with the inclusion of symbols it wouldn't surprise me if they're returning it as base64 or something. Edit to add: the final key should be exactly 16 characters/bytes long.

As for using it in tinytuya, you should be able to do it but you're going to need to figure out what data it's expecting for the different DPs. Usually the easiest way to do this is to use the app to perform an action and then look at the device logs in the IoT website to see what it sent. Sometimes you can also open a persistent connection with tinytuya and just watch for async updates sent by the device.

@mrbrdo
Copy link
Author

mrbrdo commented Dec 20, 2023

@uzlonewolf thanks. The device doesn't return any DPs though:

DEBUG:decrypted 3.x payload='{"dps":{},"type":"query","t":1702990086}'
DEBUG:payload type = <class 'str'>
DEBUG:decoded results='{"dps":{},"type":"query","t":1702990086}'
DEBUG:status() received data={'dps': {}, 'type': 'query', 't': 1702990086}
DEBUG:Detected dps: {}
result {}

Any idea why that would be?

@uzlonewolf
Copy link
Collaborator

Not all devices have persistent status, some only emit events asynchronously. I'd run a monitoring loop (i.e. https://github.com/jasonacox/tinytuya/blob/master/examples/monitor.py ) while entering something on the keypad to see if it sends an event.

I just realized Amazon has these keypads, so I should have one to play around with later today.

@uzlonewolf uzlonewolf added the tuya_device Support for specific Tuya Devices label Dec 20, 2023
@mrbrdo
Copy link
Author

mrbrdo commented Dec 21, 2023

That's awesome! I got sick and my keypads are outdoors so I didn't manage to try monitoring yet. I hope it will be possible to access the device :) Adding temporary passwords programatically would be so useful.

@uzlonewolf
Copy link
Collaborator

After poking at it a bit, it looks like you can add/change/delete codes locally but not view/list them. You may be able to pull a list from the cloud, I still need to check that. The DP description at https://developer.tuya.com/en/docs/iot/datapoint-reference?id=Kadhd28uy4rvp seems to be pretty accurate.

@mrbrdo
Copy link
Author

mrbrdo commented Dec 24, 2023

@uzlonewolf That's awesome, it's enough for my needs (don't need a list). Would you mind sharing your example code if you still have it? Will save me some time as I'm new to tinytuya.

@mrbrdo
Copy link
Author

mrbrdo commented Jan 8, 2024

@uzlonewolf do you happen to still have that code?

@uzlonewolf
Copy link
Collaborator

I do apologize for the delay, I've been really busy lately. Unfortunately I have only had a chance to look at how they communicate and haven't had a chance to write any code yet. I'll try to get something put together shortly.

@mrbrdo
Copy link
Author

mrbrdo commented Feb 2, 2024

Hey @uzlonewolf did you happen to have some time to look at this? Thanks!

@uzlonewolf
Copy link
Collaborator

Unfortunately I was not able to get it done before leaving town late last month, but I get back later this week so hopefully I'll have something for you by the weekend.

@mrbrdo
Copy link
Author

mrbrdo commented Feb 12, 2024

@uzlonewolf no worries, thanks for your time and effort!

@mrbrdo
Copy link
Author

mrbrdo commented May 6, 2024

@uzlonewolf did you manage to check it out?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tuya_device Support for specific Tuya Devices
Projects
None yet
Development

No branches or pull requests

2 participants