Hello lovely people. Long time and all that. Hope you're all doing OK.
Bit of a left field one here, looking for extra eyes more than an answer and you're the most logical bunch I know 🙂
Part of our HA system is a Logitech Elite hub and remote control.
This is programmed to control my Cyrus Stereo, our TV, and HDMI switch and our Virgin V6 box.
I've been away for a couple of days. Got back this evening to (eventually) work out that the V6 box appears to be not accepting any commands from the Logitech.
Everything has been rebooted.
Logitech uses IR to control
Cyrus: Fine
TV: Fine
HDMI: Fine
Remote control uses Bluetooth to control Hub.
All commands from the Remote to the hub are executed (one might assume correctly) as the activity LED responds, and if you're controlling (say) the Cyrus, all works fine.
iOS App can be used to control Hub over the WLAN:
All commands from the App re executed (one might assume correctly) as the activity LED responds, and if you're controlling (say) the Cyrus, all works fine.
Native remote (that uses as far as I know bluetooth) to control the V6 box works fine.
V6 box refuses to acknowledge any command other than from the native remote. Remote or app provoke absolutely zero response from the V6 box.
This is annoying, but damned if I can think of any logical reason. One might assume a firmware update on the V6 box, but given that the Hub simply emulates the native remote, that seems unlikely.
I'm struggling to think of where even to start troubleshooting this, so any random thoughts would be appreciated.
My initial approach is to buy another hub in case there's a different radio set that's failed in the hub...
TIA!
C
I currently have an HVAC system in the attic - for heating and A/C. 120v is supplied to the unit to run the gas heating. A/C uses 240v. I have an ecobee thermostat...which sometimes goes offline....not often. When it goes offline, I need to turn the 120v power to the HVAC system off and then back on (the ecobee gets its power from the HVAC system). That resets the ecobee and all is fine. I spend the summer away from this house and if the ecobee goes offine..I have no current method to reset the HVAC 120v power remotely. My idea is to replace the current 120v plug in the attic with a smart plug...then I can remotely turn the 120v power off and the ecobee will reset and come back online. I use Wyze and Lutron Casita in the house currently and was hoping I could find an in-wall smart plug from Wyze or Lutron. Obviously, I don't need diming, etc...just the ability to turn the plug power on/off. I've seen some options...but one problem I have is the attic can reach up to 135F in the summer...many of the smart plugs I've seen are not rated for that temperature. Might any of you have any thoughts on a smart plug I might want to look at? I don't want to invest in anything that would require a new hub - so either WiFi based or Casita HUB based. I need 120v and 15amp ratings. Thanks in advance.
I am trying to run a reaction that turns on lights if a sensor has not been tripped for 2 minutes. Basically, when a garage door is open, turn on inside lights if nothing has been sensed for 2 minutes. My question has to do with the expression/variable for "Last Seen". The variable never gets updated over time since the last seen event never changes.
Screenshot 2024-09-02 191632.png
In the screenshot above, the reaction checks for any garage door as well as the variable called "GarageLastEntry". The expression for this variable is displayed below:
Screenshot 2024-09-02 191651.png
The problem that I am experiencing is that the variable never changes over time. I understand that this is because the "last seen" variable does not change over time when there is no activity. In this screenshot, the value shows 0.029... This can also be seen as the current value in the original reaction screenshot above. After 10 minutes, this value should be 10. However, when a garage door is opened, the variable does not get updated and thus the rule does not become true since .029 is less than 2.
When I go to the variable and click on the > icon, the variable then gets updated as expected as seen below:
Screenshot 2024-09-02 191711.png
So the ultimate question is, how do I use a rule that can use a variable such as "last seen"? Do I need to create another variable or reaction that multiplies this by 1 every minute? From what I read in the manual, a variable is evaluated every time it is included in a reaction. But this is not what I am seeing.
I also want to ask another question related to this variable. It seems like Reactor continuously deletes this variable and I have to keep recreating it? I have never experienced this with MSR so wanted to ask if this is a common problem or if my definition is causing this.
Any info is appreciated!!!
BACKGROUND
I have been using 4 x Yale Contactless Connected Door Locks for several years (they use either a rfid tag or code to enter)
I have also been using 1 x Yale L1 Door Lock on the main front door and this connects via Yale Software
Yale contacted me to advise the L1 Lock software was being withdrawn and I needed to install a Yale Access Module into the existing lock and a Wi-Fi Bridge to link it with the newly released software
ALL of the above was working just fine.
RECENT
Yale emailed to advise I should add a Yale Access Module to each of the 4 other locks as this would link with the updated software via the Wi-Fi Bridge.
They offered a deal of just £4 each for these Modules so I got them.
THE PROBLEM
I found that only 2 of these modules would slot easily into the locks - two of them bent the pins and one of those snapped the female part in a lock (I do have a spare lock but thats not the point).
Anyway, I began to set-up the two fitted Modules with the Wi-Fi Bridge and I eventually found (thanks Google, NOT Yale) that I now need 1 x Wi-Fi Bridge PER LOCK (£50 each).
QUESTION
Does anyone know of a compatible Wi-Fi Bridge which works with Yale AND can handle multiple connections (ie 5 all 5 of my locks) ?
THANK YOU
Hello,
I had an iCOMEN boiler switch that worked for many years. And I used iCOMEN app on my phone to manage it. Short time ago app started to have an error message that it cannot connect to the server, and after some time the device also stopped working.
Some of you may know that I took at shot at building an alternate geofencing solution for Vera. The core of it was system agnostic, using the OwnTracks application and AWS lambdas to track devices and keep a central data, then disseminate that to the Vera via a websocket-based plugin. It worked with other apps as well, including Tasker and GPSLogger, but of the dozen people that were testing it, most used OwnTracks.
A lot was learned in the process, not the least of which is that the success of any such solution is highly dependent on the phone and its settings. Phone manufacturers love to set things up for the longest battery life, of course, but that's usually very anti-geofencing behavior. In the case of at least one brand, it was unusable and the settings could not be modified. It was also cost-prohibitive to maintain on Amazon, as AWS grabs a dime here and a dollar there and before you know it, it added $100/month to my AWS bill, which my wife deducted from my Scotch budget. Unacceptable.
But it's quite reasonable to use OwnTracks to a local endpoint, and I could pretty easily replicate the functionality as a local application, or maybe even as an additional endpoint built into MSR's API (still separate port and process, but in the package).
So the question really is... would you do it, or would you be too concerned about the security risks associated (e.g., dynamic DNS and NAT mapping in the firewall necessary for the phone to contact the service when not on LAN)?
Hello forum instigators.
Not sure who host/runs the forum software but a couple of challenges:
The chat is not currently usable, as the scrolling is all not right and it's not possible to read chats or send chats reliably.
There are a lot of female members that should perhaps be on another forum; where they can advertise their skills more appropriately. Note: I agree it's a job, like any other.
Whoever you are - thank you for your invaluable work.
I run a B&B and am looking for a way to turn the lights off whenever a room is unoccupied for X amount of time. The guest should still be able to turn the lights on and off manually, but should not be able to disable the auto turn off feature if the room is unoccupied.
I guess I am looking for a light switch with a built in presence sensor? I guess a presence sensor would be better as if it is a motion sensor, the lights may go off unwanted if the guest fails to make sufficient movement e.g. if the guest is lying down watching a film.
Are there any products on the market that would work for my application?
Hello,
I am in search of a device capable of using Bluetooth to connect with a smartphone and serve as its primary sound source on demand. This device should function similarly to conventional Bluetooth headphones, which automatically become the phone's sound output upon activation. However, this device should differ in that it transmits the audio signal to an amplifier via a jack, SPDIF, or similar connection. Alternatively, it could be an integrated amplifier that directly sends the signal to passive speakers.
The control of this process should be manageable through an API such as MQTT, REST, MODBUS, or similar. Are you aware of any devices that operate in this manner?
The concept is as follows: upon entering the bathroom, I would press a wall-mounted switch. This switch would send a signal to the Bluetooth device, prompting it to connect to my smartphone and seamlessly continue playing the audiobook I am currently listening to. Instead of using the phone's speakers, it would seamlessly start playing through ceiling-mounted speakers.
Many thanks 🙂
Hi folks,
I currently have some cheap Zigbee hub and some Amazon Alexas running my smart home which mostly consists of Zigbee power strips and Zigbee battery powered switches.
It all worked OK originally, but now whenever I press a Zigbee switch the light in the corresponding plug switches on then immediately off again.
If I ask Alexa to turn the light on it works fine. Likewise if I switch it on from my phone.
Any ideas what the issue could be?
I've tried unplugging the hub a number of times but that doesn't seem to fix it.
I was thinking about getting a Homey Pro 2023 to speed things up (tmas the Zigbee hub seems to be really slow now as well, for some reason) but I'm not sure about that either.
Any suggestions greatly appreciated!
Looking for a recommendation:
Locksmith is trying to talk me into the Yale Assure Lock Touchscreen with Wi-Fi and Bluetooth - the original 1st generation because they said it's built better than the Assure Lock 2. Any thoughts on this? Which would you recommend?
I see Mul T Lock makes a cylinder (KW-KIDYRL) for Yale Smart Locks. Would this fit the 1st gen Assure Lock, as well as Assure Lock 2? Has anyone tried replacing the cylinder with this on either lock?
Other smart lock I was considering is the Schlage Encode Plus.
Thanks!
Hi. So when I had my house build I ran a bunch of stuff, one of which being two pairs of speaker wires to each bedroom and to 4 spots around my living room… Over the years I have used them here and there with different success.. But today they sit in my walls just unused.
I converted all the cat6 or 5e (I don’t remember) over to basically eithernet jacks. The cable coaxial well it’s there but now unused. But I was thinking there has got to be some use for two pairs of speaker wires to each room. Can I make them usb plugs? Not sure so looking for ideas.
Thanks in advance for your thoughts on this.
Kevin
Hey guys...
We are replacing the heat pump and furnace this week and I will also need to replace my nest thermostat at the same time 'cause Nest is ending the cloud thing end of the month.
Anyway, I'm looking to use the
T6 Pro Z-Wave Programmable Thermostat | Smart Home | Honeywell HomeThat's what the heat pump installer recommend BUT, using Nest I was also using it to control the home humidifier using a single wire connected to nest... but no low voltage thermostat is able to do that, I checked all of them...
So I need some help on how I can do that, to connect the home humidifier using zwave also....
Hi
We are looking for a solution where we can detect presence of a «thing» (people , car , dog, cat, and more..
We need:
fast detections, 1-3 seconds in range from 0 to 20 m from «base» fysical «client» , chip , transmitter , unit. base , receiver placed at a door, gate, house, etc uniq Identifying wirelessThe client:
no need for pressing any thing (no buttons) battery , hoply 2-5 years battery time.Have someone done anything like this?
What technologi will be best?
Hey everyone, I'm currently working on developing a bed sensor that can detect when you're out of bed. It could be used to trigger other smart home gadgets, like lights or blinds, temperature etc.
The sensors are placed under the legs of your bed post. Should look and feel like "smart furniture pads" with size 2 inches in diameter and 1/4 inch thick.
Before we go any further, I'd love to get your thoughts on this - would a bed sensor like this be something you'd find useful? We're still in the early stages of development, so any feedback you have would be greatly appreciated. Thanks in advance!
@DesT, fenced code blocks display differently after the upgrade.
abc defThe above should display as abc and def on two separate lines. This works. But this fails:
verbose: true config: data: "auto"The above should display as three lines, verbose: true, config: and data: "auto", but this fails. In order to make it display properly, I now have to open the fenced code block with ```text (specify language, generic text). This displays without highlighting. The words yml and yaml (and the all-caps versions) don't seem to be recognized. I can also use js to get JavaScript highlighting, but this isn't great for YAML. Here's the same block with the language (text) specifier added (no other changes):
verbose: true config: data: "auto"Sure, we can start adding language specifiers to our new posts, but I suspect if we start digging around old posts, we're going to find a lot of broken display of the fenced code blocks (plain ``` at the start with no language specifier) in the thousands of old posts in these forums, upon which people still rely for answers and information.
Log file snippets also get similarly brutalized:
[###BUILDVERSION###]2023-04-26T19:41:51.683Z <ZWaveJSController:NOTICE> ZWaveJSController#zwavejs added file logger to zwavejs.log [###BUILDVERSION###]2023-04-26T19:41:51.747Z <ZWaveJSController:WARN> zwavejs_capabilities defines x_zwave_device_cfg, which is not consistent with the recommended naming [###BUILDVERSION###]2023-04-26T19:41:51.747Z <ZWaveJSController:WARN> zwavejs_capabilities defines x_zwave_mfg_spec, which is not consistent with the recommended naming [###BUILDVERSION###]2023-04-26T19:41:51.747Z <ZWaveJSController:WARN> zwavejs_capabilities defines x_zwave_device_ver, which is not consistent with the recommended naming [###BUILDVERSION###]2023-04-26T19:41:51.747Z <ZWaveJSController:WARN> zwavejs_capabilities defines x_zwave_values, which is not consistent with the recommended naming [###BUILDVERSION###]2023-04-26T19:41:51.837Z <ZWaveJSController:INFO> ZWaveJSController#zwavejs connecting to ws://192.168.0.10:3000 [###BUILDVERSION###]2023-04-26T19:41:51.874Z <ZWaveJSController:NOTICE> ZWaveJSController#zwavejs connected [###BUILDVERSION###]2023-04-26T19:41:51.874Z <ZWaveJSController:INFO> ZWaveJSController#zwavejs sending connection initialization [###BUILDVERSION###]2023-04-26T19:41:51.931Z <ZWaveJSController:INFO> ZWaveJSController#zwavejs greeting from server: [Object]{ "type": "version", "driverVersion": "10.16.0", "serverVersion": "1.28.0", "homeId": 3631280043, "minSchemaVersion": 0, "maxSchemaVersion": 28 } [###BUILDVERSION###]2023-04-26T19:41:51.932Z <ZWaveJSController:INFO> ZWaveJSController#zwavejs performing initial inventory [###BUILDVERSION###]2023-04-26T19:41:52.325Z <ZWaveJSController:INFO> ZWaveJSController#zwavejs manufacturer-specific data for 134 (AEON Labs) from package ver 22315.1 [###BUILDVERSION###]2023-04-26T19:41:52.328Z <ZWaveJSController:INFO> ZWaveJSController#zwavejs configuring node 1 endpoint 0 (entity "1-0") [###BUILDVERSION###]2023-04-26T19:41:52.339Z <ZWaveJSController:INFO> ZWaveJSController#zwavejs manufacturer-specific data for 543 (Elexa Consumer Products Inc.)I think this is going to be a problem. Is there a way in NodeBB to configure the default language for fenced code block markdown for the entire forum so that these display more as they did before the upgrade?
EDIT: Examples below of old posts with corrupt formatting now:
https://smarthome.community/topic/1101/dynamic-groups-controller-filter-expressions
https://smarthome.community/post/11362
This last old post is interesting, because the first block displays incorrectly, but the second block is OK. In playing around, there seem to be triggering character sequences, suggesting that the markdown processor is trying to "guess" the language but not getting it right, perhaps:
Can anyone help with the MIOS UI5 weblink? Not the getvera one.
Still running UI5 on a couple of sensors & lights and need to tweak PLEG but for the life of me I can't remember the link to tunnel back to the trusty machine....
Lua - Code to encrypt / decrypt with AES 128 CBC
-
Well the key you show is definitely not hex, because 16 bytes of hex should be 32 characters long with only 0-9, A-F. Looks like you have base64 for the key, not hex.
-
Progress at last ! well I’ve at least got the key and iv in the correct hex format for the OpenSSL aes cbc encryption command to work.🥳
Which leads me on to the next part, where the output of the above is referred to as the ciphertext;, of which I now need to do the following with..
ciphertext = MyopensslAEScbcCall() sig = encdec.hmacsha256(ciphertext, hmac_key, true) encrypted_payload = encdec.base64enc(ciphertext .. sig) return encrypted_payload
hmacsha256
seems to be next, and it might also be something I could do with OpenSSL too ? -> https://unix.stackexchange.com/questions/610039/how-to-do-hmacsha256-using-openssl-from-terminal ?I also found this too - https://github.com/jqqqi/Lua-HMAC-SHA256/blob/master/sha256.lua
@toggledbits any suggestions/recommendations on what to do with this next part ?
-
I would stick with OpenSSL. You just need to assemble the correct bits (HMAC key and ciphertext) to send to the hash function, compute the hash, then append the hash to the ciphertext. The trick here will be that you currently have the AES encyption outputting its result base64-encoded... you can't append the signature to that. You need the ciphertext output in binary for that, so you need to remove the
-a
(and-A
) to let the output be binary. Then you can put that into the hash. And then you can take the (binary) hash output and append that to the binary ciphertext, and then you base64 encode the assembled result at the very end. The whole thing takes a few steps. I would recommend writing a shell script to do all the steps, and just have Lua run the shell script. You can then more easily develop and test the steps (because they are all in the shell script and runnable from the command line). -
Thanks @toggledbits - I struggle enough with Lua, so i admire your optimism in thinking I could create a shell script too
I must admit, I can’t help but feel like I’m making this more complicated that it needs to be, especially as there are working Lua and Python scripts already out there, which seem to be doing everything natively (although I do admit much of this thread is trying to plug holes in Vera )
With that said, the following might help you understand the bigger picture of what I’m trying to replicate, and maybe help me more, as I found some related posts, the first one which uses python e.g. https://github.com/florianholzapfel/panasonic-viera/issues/9 - and I’ve extracted the related HMAC part below.
… # Let's encrypt it with AES-CBC! We need to make sure we pad it to a multiple of 16 bytes beforehand aes = AES.new(key, AES.MODE_CBC, iv) ciphertext = aes.encrypt(pad(payload)) # Calculate the HMAC-SHA-256 signature of our encrypted payload sig = hmac.new(hmac_key, ciphertext, hashlib.sha256).digest() # Concatenate the HMAC signature to the encrypted payload and base64 encode it, and we're done! encrypted_payload = base64.b64encode(ciphertext + sig)
Plus there’s this pure Lua version called Haslib -> https://github.com/howmanysmall/Rewrites/blob/master/src/HashLib.lua - which looks like it might be promising to add to Vera as a module ?
USAGE: Input data should be a string Result (SHA digest) is returned in hexadecimal representation as a string of lowercase hex digits. Simplest usage example: local HashLib = require(script.HashLib) local your_hash = HashLib.sha256("your string")
Looking at the functions within the latter HashLib.lua file, it has one called
local function hmac(hash_func, key, message)
which makes me wonder could i use that and do the following.. ?local HashLib = require(script.HashLib) local mySig = HashLib.hmac(sha256, ciphertext, hmac_key)
-
Approach however you want, it's yours to choose, of course. I can just recommend (and you asked). My experience is that snatching random code snippets from Github can be hit or miss, and if it's a miss, it will take longer to find because of your implicit trust of "working" code by others. OpenSSL is widely-used and well-known. It is, for practical purposes, a reference standard. If you find "good code" on Github and it turns out it isn't, it will likely be a long time before you figure it out, because you'll trust it, even though you should not. And in this scenario, with so much computation, and in so many steps, it's all a black box and debugging any piece of it will be extremely challenging. You'll post here when it doesn't work and I and anyone else won't be able to help you, because we can verify it either. Using a known-good tool, even if you struggle to get to know it, will give you a more reliable result, because then you are only fighting with your handling of the inputs and outputs and getting the steps right and in the right order. You should use the best tools possible to minimize the number of variables in the equation. Once you know how it all works, you see it all hang together, and you've got some "sand in your pants" as they say, then you can start replacing with other things, if necessary.
The other issue is that no Lua implementation, of crypto in particular, which can be very complex and iterative, is going to be more efficient than the C/C++-based, optimized implementation of OpenSSL. That matters on the weak CPUs we are working with.
At a minimum, you should get your procedure working on the command line, with all the steps and a full cycle of encode and decode with a couple of different payloads. Once you have that, you have something (known inputs and known outputs/results) you can use to test Lua replacements, because you have known benchmarks to compare to. If you don't know what a particular input will produce on the output, you will never know if any piece of code you find is correct or not.
-
Thanks so much @toggledbits for your open and honest feedback, I really appreciate it. Taking your advice I’m going to persist with OpenSSL to get this next encrypted payload step done.
How does this set of next steps look to you ..?
Step 1, Adjust the OpenSSL ciphertext aes-cbc command, so it outputs in binary (do this by removing the -a (and -A) parameters ).
Step 2, When it comes to the hmac_key , it looks like it created in the following way, and as I can’t see any hex or base64 references, onlybit
- is it already using the right binary format ?local bit = require("bit") local binascii = require("binascii") function createHMACKey() local iv_vals = { iv:byte(1, -1) } local hmac_key_mask = binascii.unhexlify('15C95AC2B08AA7EB4E228F811E34D04FA54BA7DCAC9879FA8ACDA3FC244F3854') local hmac_key_mask_vals = { hmac_key_mask:byte(1, -1) } local hmac_vals = {} for i = 1, 32, 4 do hmac_vals[ i ] = bit.bxor(hmac_key_mask_vals[ i ], iv_vals[ bit.band(i + 1, 0xF) + 1 ]) hmac_vals[ i + 1 ] = bit.bxor(hmac_key_mask_vals[ i + 1 ], iv_vals[ bit.band(i + 2, 0xF) + 1 ]) hmac_vals[ i + 2 ] = bit.bxor(hmac_key_mask_vals[ i + 2 ], iv_vals[ bit.band(i - 1, 0xF) + 1 ]) hmac_vals[ i + 3 ] = bit.bxor(hmac_key_mask_vals[ i + 3 ], iv_vals[ bit.band(i, 0xF) + 1 ]) end local hmac_key = string.char(unpack(hmac_vals)) print(hmac_key) return hmac_key end createHMACKey()
Step 3. Use openSSL to encrypt the binary ciphertext and binary hmac_key with hmacsha256 to create the
sig
(signature)
Step 4. Then using mime.base64, encrypt the ciphertext with the new singnature to create thepayload
-
Hi @toggledbits
If/when you have time , I’d really appreciate some further help..
Quick reminder of my current goal, which is to convert the following 3 steps, so an equivalent can run on Vera.
One..
aes_cbc, err = aes:new(key, nil, aes.cipher(128, 'cbc'), { iv = iv }, nil, 1) ciphertext = aes_cbc:encrypt(payload)
Two..
sig = encdec.hmacsha256(ciphertext, hmac_key, true)
Three..
encrypted_payload = encdec.base64enc(ciphertext .. sig)
@toggledbits said in Lua - Code to encrypt / decrypt with AES 128 CBC:
You just need to assemble the correct bits (HMAC key and ciphertext) to send to the hash function, compute the hash, then append the hash to the ciphertext.
You make it sound so easy, I’d love to get this to work..
The trick here will be that you currently have the AES encyption outputting its result base64-encoded...
Looking at the guide (https://linux.die.net/man/1/openssl ) I’m trying to see how the command results in a the output being base64 encoded ?
opensslAES128command = "openssl enc -aes-128-cbc -nosalt -e -a -A -in etc/payload.txt -K "..key.." -iv "..iv.." -out etc/payload2.txt"
The above command output this....
gGBjfMi+lMGhQYdhjy1UWuRCtY1WIE07CmQ5aW/jITDYbe8I01QxtYfXzkpk4km8
you can't append the signature to that. You need the ciphertext output in binary for that, so you need to remove the
-a
(and-A
) to let the output be binary.I also tried the above command, without both the -a -A options and it returns this…
€`c|Ⱦ”Á¡A‡a-TZäBµV M; d9ioã!0ØmïÓT1µ‡×ÎJdâI¼
is this binary ?
Then you can put that into the hash.
Next when you say
hash
do you mean the second part, the encdec.hmacsha256 piece ? If so what exactly am I hashing ? Are (ciphertext, hmac_key, true) all concatenation into one long string ? Like this maybe ?openssl dgst -sha256 -hmac $(<etc/my ciphertext,-hmac_key.txt) etc/hmacoutput.txt
And then you can take the (binary) hash output and append that to the binary ciphertext, and then you base64 encode the assembled result at the very end.
With mime.b64 I think, I’m good on the last step ..
The whole thing takes a few steps.
Totally agree I just need to ensure I have right ones ?
-
I’m still persevering with this one, but something’s not quite right, so hopefully the following with help people help me..
- I send a request to the TV to obtain a PIN Code, which it presents on the screen e.g 1234
- It also provides me with a Challenge Key.
--[[ challenge key returned will be something like this.. <?xml version="1.0" encoding="utf-8"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:X_DisplayPinCodeResponse xmlns:u="urn:panasonic-com:service:p00NetworkControl:1"> <X_ChallengeKey>iL9XqQOMfkFWz2rvh0Xm+w==</X_ChallengeKey> </u:X_DisplayPinCodeResponse> </s:Body> </s:Envelope>
I extract the challenge key and store it, and to give me options, I also store a base64 and a Hex version too.
challenge_Key = string.match(pairing_res,'<X_ChallengeKey>(.*)</X_ChallengeKey>') luup.variable_set(PANI_SERV,"challenge_Key",challenge_Key,DEVICE) local iv_b64 = mime.b64(challenge_Key) luup.variable_set(PANI_SERV,"iv_b64",iv_b64,DEVICE) local iv_HEX = binascii.hexlify(challenge_Key) luup.variable_set(PANI_SERV,"iv_HEX",iv_HEX,DEVICE)
Which gives me..
challenge_Key = 6Sj5RAitzqplQ860TviWLw== challenge_Key_b64 = NlNqNVJBaXR6cXBsUTg2MFR2aVdMdz09 challenge_Key_HEX = 36536A35524169747A71706C51383630547669574C773D3D
So far so good, and going forward base64 version will be known as IV.
Next step is to take the IV and create a KEY and a HMAC_KEY, which I do the following way..
1st the KEY
local iv = luup.variable_get(PANI_SERV,"iv", DEVICE) local iv_vals = { iv:byte(1, -1) } local key_vals = {} for i = 1, 16, 4 do key_vals[ i ] = bit.band(bit.bnot(iv_vals[ i + 3 ]), 0xFF) key_vals[ i + 1 ] = bit.band(bit.bnot(iv_vals[ i + 2 ]), 0xFF) key_vals[ i + 2 ] = bit.band(bit.bnot(iv_vals[ i + 1 ]), 0xFF) key_vals[ i + 3 ] = bit.band(bit.bnot(iv_vals[ i ]), 0xFF) end local key = string.char(unpack(key_vals)) luup.variable_set(PANI_SERV,"key",key,DEVICE)
And then the HMAC_KEY
local hmac_key_mask = binascii.unhexlify('15C95AC2B08AA7EB4E228F811E34D04FA54BA7DCAC9879FA8ACDA3FC244F3854') local hmac_key_mask_vals = { hmac_key_mask:byte(1, -1) } local hmac_vals = {} for i = 1, 32, 4 do hmac_vals[ i ] = bit.bxor(hmac_key_mask_vals[ i ], iv_vals[ bit.band(i + 1, 0xF) + 1 ]) hmac_vals[ i + 1 ] = bit.bxor(hmac_key_mask_vals[ i + 1 ], iv_vals[ bit.band(i + 2, 0xF) + 1 ]) hmac_vals[ i + 2 ] = bit.bxor(hmac_key_mask_vals[ i + 2 ], iv_vals[ bit.band(i - 1, 0xF) + 1 ]) hmac_vals[ i + 3 ] = bit.bxor(hmac_key_mask_vals[ i + 3 ], iv_vals[ bit.band(i, 0xF) + 1 ]) end local hmac_key = string.char(unpack(hmac_vals)) luup.variable_set(PANI_SERV,"hmac_key",hmac_key,DEVICE)
This then gives me the following..
Key = Ž±“±½µ©±É§žŒ½§œ key_HEX = 8EB193B1BDB5A9B1C9ADA79E8CBDA79C hmac_key = [¸®úÈé½îÙ\G³ë:é°æÚ7¬Øû¤f<[ hmac_key_HEX = 5BB814AEFAC8E9BD1C14EED95C47B317EB3AE9B0E6DA37ACD8FBC2A4663C5B0C
Once I have these available I then need to create the payload which these will be used to help encrypt etc.
The payload creation process is uses the PIN number presented at the very start.local data = "<X_PinCode>5852</X_PinCode>" local payload = '000000000000' local n = #data payload = payload .. string.char(bit.band(bit.rshift(n, 24), 0xFF)) payload = payload .. string.char(bit.band(bit.rshift(n, 16), 0xFF)) payload = payload .. string.char(bit.band(bit.rshift(n, 8), 0xFF)) payload = payload .. string.char(bit.band(n, 0xFF)) payload = payload .. data luup.variable_set(PANI_SERV,"payload",payload,DEVICE)
Which returns this.
payload = 0000000000005852
The modules I have in use are as follows..
local bit = require("bit") local mime = require("mime") local binascii = require("binascii")
Does all of the above look correct?
These are important parts to take this into the openSSL requests earlier in this thread, which so far (used as HEX) are throwing errors (invalid/too long)
-
Calling the likes of @toggledbits , @akbooer , @therealdb to help check my logic below, as I’ve been trying to get this to work for a while now, and feel I need to step back and just check some of the basics are correct, before I even get into the ciphers/encryption part..
Here goes, using a http command , I can get a random PIN number (e.g. 1234) and the following XML response back from the TV, as it’s the
Challenge_key
I need first, I extract that..<?xml version="1.0" encoding="utf-8"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:X_DisplayPinCodeResponse xmlns:u="urn:panasonic-com:service:p00NetworkControl:1"> <X_ChallengeKey>iL9XqQOMfkFWz2rvh0Xm+w==</X_ChallengeKey> </u:X_DisplayPinCodeResponse> </s:Body> </s:Envelope>
Guidance online suggests I then need to encode that in Base64, which would be this..
local mime = require("mime") local challenge_key = "iL9XqQOMfkFWz2rvh0Xm+w==" local challenge_Key_b64 = mime.b64(challenge_key) print (challenge_Key_b64)
Which gives me this..
aUw5WHFRT01ma0ZXejJydmgwWG0rdz09
To then get the
key
which I assume is the real encryption key, it looks like I would do the following…local bit = require("bit") local challenge_Key_b64 = "aUw5WHFRT01ma0ZXejJydmgwWG0rdz09" local challengekey_vals = { challenge_Key_b64:byte(1, -1) } local key_vals = {} for i = 1, 16, 4 do key_vals[ i ] = bit.band(bit.bnot(challengekey_vals[ i + 3 ]), 0xFF) key_vals[ i + 1 ] = bit.band(bit.bnot(challengekey_vals[ i + 2 ]), 0xFF) key_vals[ i + 2 ] = bit.band(bit.bnot(challengekey_vals[ i + 1 ]), 0xFF) key_vals[ i + 3 ] = bit.band(bit.bnot(challengekey_vals[ i ]), 0xFF) end local key = string.char(unpack(key_vals)) print(key)
Which give me this..
ʈªž¹·¨’ÎÏ«§¥Ïž
I’m conscious at this point that I’m using a web based Lua IDE, so I’m not sure if the values returned are accurate, plus @toggledbits has recommended HEX which sounds ideal, but for now I just want to be sure I’m working through it correctly?
Continuing on, next step is to get the
hmac_val
- and it looks like I need to use the samechallengekey_vals
to generate thehmac_key
local bit = require("bit") local binascii = require("binascii") local challengekey_64 = "aUw5WHFRT01ma0ZXejJydmgwWG0rdz09" local challengekey_vals = { challengekey_64:byte(1, -1) } local hmac_key_mask = binascii.unhexlify('15C95AC2B08AA7EB4E228F811E34D04FA54BA7DCAC9879FA8ACDA3FC244F3854') local hmac_key_mask_vals = { hmac_key_mask:byte(1, -1) } local hmac_vals = {} for i = 1, 32, 4 do hmac_vals[ i ] = bit.bxor(hmac_key_mask_vals[ i ], challengekey_vals[ bit.band(i + 1, 0xF) + 1 ]) hmac_vals[ i + 1 ] = bit.bxor(hmac_key_mask_vals[ i + 1 ], challengekey_vals[ bit.band(i + 2, 0xF) + 1 ]) hmac_vals[ i + 2 ] = bit.bxor(hmac_key_mask_vals[ i + 2 ], challengekey_vals[ bit.band(i - 1, 0xF) + 1 ]) hmac_vals[ i + 3 ] = bit.bxor(hmac_key_mask_vals[ i + 3 ], challengekey_vals[ bit.band(i, 0xF) + 1 ]) end local hmac_key = string.char(unpack(hmac_vals)) print(hmac_key)
Which give me this…
bü;—öØð£OÛ±Dl±Ò~ƉêÊ.²» ÷Ì~Yd
And then I think to get the IV, i would do the following.
local bit = require("bit") local payload = '000000000000' -- First 12 bytes are randomised local pincode = "<X_PinCode>1234</X_PinCode>" -- Next 4 bytes are from the pincode prompted by the TV n = #pincode payload = payload .. string.char(bit.band(bit.rshift(n, 24), 0xFF)) payload = payload .. string.char(bit.band(bit.rshift(n, 16), 0xFF)) payload = payload .. string.char(bit.band(bit.rshift(n, 8), 0xFF)) payload = payload .. string.char(bit.band(n, 0xFF)) payload = payload .. pincode local iv = payload print(iv)
Which returns this ..
0000000000001234
Does all of the above look correct to create the 3 items needed below.. ?
Key = ʈªž¹·¨’ÎÏ«§¥Ïž HMAC_KEY = bü;—öØð£OÛ±Dl±Ò~ƉêÊ.²» ÷Ì~Yd IV = 0000000000001234
-
@parkerc said in Lua - Code to encrypt / decrypt with AES 128 CBC:
Guidance online suggests I then need to encode that in Base64, which would be this..
Looks to me that iL9XqQOMfkFWz2rvh0Xm+w== is already in base64, and that would make sense, given that's been sent to you via HTTP.
-
Thanks @akbooer - you’re so right i cant believe i missed that, I’m supposed to decode, not encode ! Doh !!
FYI - Here’s the source.. https://github.com/florianholzapfel/panasonic-viera/issues/9#issuecomment-476919658
How did the rest look ? Here’s my Lua inline with the source.
-- import binascii -- import base64 -- import hmac, hashlib -- from Crypto.Cipher import AES local bit = require("bit") local mime = require("mime") local binascii = require("binascii") -- # Example challenge (which is our IV) -- iv = base64.b64decode("mUQdS7/RyJTMsiojPz9i1Q==") local challenge_key = "iL9XqQOMfkFWz2rvh0Xm+w==" local challenge_Key_unb64 = mime.unb64(challenge_key) print (challenge_Key_unb64) -- # Get character codes from IV bytes -- iv_vals = [ord(c) for c in iv] -- # Initialise key character codes array -- key_vals = [0] * 16 -- # Derive key from IV -- i = 0 -- while i < 16: -- key_vals[i] = ~iv_vals[i + 3] & 0xFF -- key_vals[i + 1] = ~iv_vals[i + 2] & 0xFF -- key_vals[i + 2] = ~iv_vals[i + 1] & 0xFF -- key_vals[i + 3] = ~iv_vals[i] & 0xFF -- i += 4 -- # Convert our key character codes to bytes -- key = ''.join(chr(c) for c in key_vals) local challenge_Key_unb64 = "ˆ¿W©Œ~AVÏjï‡Eæû" local challengekey_vals = { challenge_Key_unb64:byte(1, -1) } local key_vals = {} for i = 1, 16, 4 do key_vals[ i ] = bit.band(bit.bnot(challengekey_vals[ i + 3 ]), 0xFF) key_vals[ i + 1 ] = bit.band(bit.bnot(challengekey_vals[ i + 2 ]), 0xFF) key_vals[ i + 2 ] = bit.band(bit.bnot(challengekey_vals[ i + 1 ]), 0xFF) key_vals[ i + 3 ] = bit.band(bit.bnot(challengekey_vals[ i ]), 0xFF) end local key = string.char(unpack(key_vals)) print(key) -- "V¨@w¾sü•0©ºx " -- # Initialise HMAC key mask (taken from libtvconnect.so) -- hmac_key_mask_vals = [ord(c) for c in binascii.unhexlify("15C95AC2B08AA7EB4E228F811E34D04FA54BA7DCAC9879FA8ACDA3FC244F3854")] -- # Initialise HMAC key character codes array -- hmac_vals = [0] * 32 -- # Calculate HMAC key using HMAC key mask and IV -- i = 0 -- while i < 32: -- hmac_vals[i] = hmac_key_mask_vals[i] ^ iv_vals[(i + 2) & 0xF] -- hmac_vals[i + 1] = hmac_key_mask_vals[i + 1] ^ iv_vals[(i + 3) & 0xF] -- hmac_vals[i + 2] = hmac_key_mask_vals[i + 2] ^ iv_vals[i & 0xF] -- hmac_vals[i + 3] = hmac_key_mask_vals[i + 3] ^ iv_vals[(i + 1) & 0xF] -- i += 4 -- # Convert our HMAC key character codes to bytes -- hmac_key = ''.join(chr(c) for c in hmac_vals) local challenge_Key_unb64 = "ˆ¿W©Œ~AVÏjï‡Eæû" local challengekey_vals = { challenge_Key_unb64:byte(1, -1) } local hmac_key_mask = binascii.unhexlify('15C95AC2B08AA7EB4E228F811E34D04FA54BA7DCAC9879FA8ACDA3FC244F3854') local hmac_key_mask_vals = { hmac_key_mask:byte(1, -1) } local hmac_vals = {} for i = 1, 32, 4 do hmac_vals[i] = bit.bxor(hmac_key_mask_vals[ i ], challengekey_vals[ bit.band(i + 1, 0xF) + 1 ]) hmac_vals[i+1] = bit.bxor(hmac_key_mask_vals[ i + 1 ], challengekey_vals[ bit.band(i + 2, 0xF) + 1 ]) hmac_vals[i+2] = bit.bxor(hmac_key_mask_vals[ i + 2 ], challengekey_vals[ bit.band(i - 1, 0xF) + 1 ]) hmac_vals[i+3] = bit.bxor(hmac_key_mask_vals[ i + 3 ], challengekey_vals[ bit.band(i, 0xF) + 1 ]) end local hmac_key = string.char(unpack(hmac_vals)) print(hmac_key) --"B`Ò}Îˤg$ÍÙNøÏWòâ/cÒÙzvà"õ3´¿"" -- # This is our plaintext SOAP argument for the pin code shown on the TV -- authinfo = "<X_PinCode>4410</X_PinCode>" -- # First 12 bytes are randomised, let's just set them to 0 because it doesn't matter -- payload = "000000000000" -- # The next 4 bytes contain the plaintext (SOAP arg) length in big endian -- n = len(authinfo) -- payload += chr(n >> 24) -- payload += chr((n >> 16) & 0xFF) -- payload += chr((n >> 8) & 0xFF) -- payload += chr(n & 0xFF) -- # Now we concatenate our payload, which is starting at byte 17 of the payload -- payload += authinfo local payload = '000000000000' -- First 12 bytes are randomised local pincode = "<X_PinCode>1234</X_PinCode>" -- Next 4 bytes are from the pincode prompted by the TV n = #pincode payload = payload .. string.char(bit.band(bit.rshift(n, 24), 0xFF)) payload = payload .. string.char(bit.band(bit.rshift(n, 16), 0xFF)) payload = payload .. string.char(bit.band(bit.rshift(n, 8), 0xFF)) payload = payload .. string.char(bit.band(n, 0xFF)) payload = payload .. pincode local iv = payload print(iv) -- "0000000000001234" -- # Let's encrypt it with AES-CBC! We need to make sure we pad it to a multiple of 16 bytes beforehand -- aes = AES.new(key, AES.MODE_CBC, iv) -- ciphertext = aes.encrypt(pad(payload)) -- # Calculate the HMAC-SHA-256 signature of our encrypted payload -- sig = hmac.new(hmac_key, ciphertext, hashlib.sha256).digest() -- # Concatenate the HMAC signature to the encrypted payload and base64 encode it, and we're done! -- encrypted_payload = base64.b64encode(ciphertext + sig)
Still the AES/CBC bit to get working, but hopefully this is progress..