HTTPS/SSL Support and Password Obfuscation Control#13
HTTPS/SSL Support and Password Obfuscation Control#13gierwialo wants to merge 4 commits intopuddly:devfrom
Conversation
puddly
left a comment
There was a problem hiding this comment.
Thanks! I've left a few comments about the code.
Is the password obfuscation setting something we can autodetect? Possibly from the API version (if that's exposed unauthenticated) or just by trying both approaches?
|
Thanks! This looks good to me. Run @chiconws Home Assistant doesn't have a way to pin certificates to devices, it looks like the only choice during setup is to detect certificate validation errors during connection and present a new step in the config flow to allow users to opt into bypassing validation. Is this something you want to support? |
|
Yeah, I think we should support it, since there’s already a user request. Because we can’t reliably check HTTPS state before authentication, I’d handle it in this order: Try HTTP first; if it works, continue as normal |
I recently bought a NanoKVM Pro PCI-E and wanted to connect to it over HTTPS from Python. Turns out the library didn't support SSL/TLS at all, so I added it. While testing, I ran into a weird authentication issue that led me down a rabbit hole...
"The Authentication Mystery"
When I tried connecting to my NanoKVM Pro (running Application v1.2.12, Image v1.0.13) over HTTPS, authentication kept failing with "Invalid username or password" - even though I was using the correct credentials!
After SSH'ing into the device and monitoring logs, I discovered the reason: the library was sending AES-256-CBC encrypted passwords, but my device expected plain text over HTTPS (it does bcrypt hashing server-side). The web UI was working fine because it sends passwords in plain text.
Turns out newer NanoKVM versions (Pro and Standard ≥2.1.6) switched to accepting plain text passwords over HTTPS, while older versions still need the client-side obfuscation.
Note: NanoKVM Pro uses different version numbering (1.x.x) than standard NanoKVM (2.x.x), which initially confused me - I thought v1.2.12 was ancient!
What I Added
1. SSL/TLS Support
Three new optional parameters for
NanoKVMClient.__init__():verify_ssl: bool = True- Enable/disable SSL certificate verificationFalsefor self-signed certs (testing only)ssl_ca_cert: str | None = None- Path to custom CA certificateImplementation details:
aiohttp.TCPConnectorwith SSL configNanoKVMSSLErrorexception2. Password Obfuscation Control
One new parameter to handle the authentication differences:
use_password_obfuscation: bool = True- Control password encryptionTrue(backward compatible with older devices)Falsefor modern NanoKVM with HTTPSTrue: Uses AES-256-CBC encryption (legacy behavior)False: Sends plain text (relies on HTTPS transport security)Backward Compatibility
Everything is 100% backward compatible. Existing code works without changes:
All new parameters have sensible defaults:
verify_ssl=True- Secure by defaultuse_password_obfuscation=True- Works with older devicesTesting
I tested everything with my actual NanoKVM Pro over HTTPS:
use_password_obfuscation=False)Usage Examples
NanoKVM with HTTPS (Recommended)
Legacy NanoKVM with HTTP
Self-Signed Certificates
Technical Details
SSL Implementation
ssl.create_default_context()for secure defaultsPassword Obfuscation
EncryptSecretKeyFiles Changed
nanokvm/client.py- Main implementation (~150 lines added/modified)tests/test_ssl.py- New comprehensive SSL tests (~200 lines)README.md- Updated docs with HTTPS examplesVersion Compatibility Guide
Based on my testing and research:
Modern devices (use plain text password):
→ Set
use_password_obfuscation=FalseLegacy devices (need obfuscation):
EncryptSecretKey→ Keep
use_password_obfuscation=True(default)Not sure which you have?
use_password_obfuscation=FalseMy Test Setup
Device: NanoKVM Pro PCI-E
Software: Application v1.2.12, Image v1.0.13 (latest for Pro line)
Certificate: Let's Encrypt
Protocol: HTTPS with TLS 1.3
Authentication: Plain text password (
use_password_obfuscation=False)Result: Everything works perfectly for me ;-)
Feel free to comment and review what I've done :)
Review changes
Auto-Detection of Password Obfuscation Mode
Based on suggestion, the client now automatically detects whether the device needs obfuscated or plain text passwords — no manual configuration needed.
use_password_obfuscation: bool | None = None- Changed frombool = TruetoOptional[bool]None(default): Auto-detect — tries obfuscated first, falls back to plain textTrue: Force obfuscation (legacy behavior)False: Force plain textHow auto-detect works:
NanoKVMAuthenticationFailure→ retry with plain textThis means existing code works without changes and without the extra parameter:
Other Review Fixes
NanoKVMSSLError— SSL exceptions (FileNotFoundError,ssl.SSLError) now propagate naturally fromssl.create_default_context()instead of being wrapped_create_ssl_context()is offloaded viaasyncio.to_thread()since it performs file IOasync def test_*functions, no classes, consistent with the rest of the test suite