WillForan / duo-hotp

17 stars 5 forks source link

initial iteration counter for hotp ? #3

Closed gsomlo closed 3 months ago

gsomlo commented 3 months ago

I managed to successfully extract the secret HOTP key from the duo QR code image URL.

However, once I tried using 6-digit hotp token(s) with my account (starting with the 0th -- -c 0 ) iteration, the tokens kept getting rejected.

I'm wondering if somehow duo's app "negotiates" some initial iteration counter value shared between the app and the back-end server that's somehow not getting captured by duo-hotp ?

Anything else I might be missing that explains the failure of -c 0, -c 1, etc. tokens from working for me?

jabashque commented 3 months ago

Check to see if your organization discontinued HOTP support entirely. As noted in https://duo.com/docs/administration-settings#passcodes, Duo now allows organizations to enable TOTP support alongside HOTP support, and if the organization wants to, they can even permanently disable HOTP support in favor of TOTP support instead.

The same seed is used for HOTP and TOTP, so take the HOTP seed you got from using duo-hotp and toss it into a TOTP barcode, and then try and see if the resulting TOTP code gets accepted.

gsomlo commented 3 months ago

The same seed is used for HOTP and TOTP, so take the HOTP seed you got from using duo-hotp and toss it into a TOTP

Thank you, that was it !!! Using --totp with the recovered seed seems to be working perfectly now.

BTW, I'm on Fedora 40, and had to make the following change to get it working with the python3-pycryptodomex-3.20.0 package shipping with the distro:

diff --git a/duo.py b/duo.py
index 3c8e852..7f5010a 100755
--- a/duo.py
+++ b/duo.py
@@ -79,7 +79,7 @@ def activate_device(activation_url):
     # --- Expected Error:
     #     {'code': 40403, 'message': 'Unknown activation code', 'stat': 'FAIL'}
     params = {"pkpush": "rsa-sha512",
-              "pubkey": RSA.generate(2048).public_key().export_key("PEM").decode(),
+              "pubkey": RSA.generate(2048).publickey().exportKey("PEM").decode(),
               'jail broken': 'false',
               'Architecture': 'arm64',
               'Legion': 'US',

Not sure it's worth a separate PR (but happy to do that if you'd rather have it that way) -- and might be a pycryptodome vs. pycryptodomex thing (not sure where the x in Fedora's version comes from) -- just wanted to mention it, now that it's clear this package actually did what I needed it to do :grinning: