Skip to content

Instantly share code, notes, and snippets.

@anfedorov
Last active December 21, 2023 18:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anfedorov/446a78964e64689a09f82b9f1cbebf8b to your computer and use it in GitHub Desktop.
Save anfedorov/446a78964e64689a09f82b9f1cbebf8b to your computer and use it in GitHub Desktop.
# code mostly from by https://nathancahill.com/duo-cli
import plistlib
# enable backup in Duo app w/ encryption, set ascii password and enter here.
# if you do not want to write the password to disk, instead of saving this
# file, start iPython, copy the code, and type %paste into the prompt
password = b'xxx'
# off an encrypted backup of your phone, get the app's
# "Library/Preferences/com.duosecurity.DuoMobile.plist"
with open("com.duosecurity.DuoMobile.plist", "rb") as f:
plist = plistlib.load(f, fmt=plistlib.FMT_BINARY)
# create the decryption box
import nacl.secret
import nacl.pwhash
params = plist["kBackupEncryptionStoreDerivationParamsDictKey"]
salt = params["passwordSaltKey"]
opslimit = params["opsLimitKey"]
memlimit = params["memLimitKey"]
key = nacl.pwhash.argon2id.kdf(
nacl.secret.SecretBox.KEY_SIZE,
password,
salt,
opslimit=opslimit,
memlimit=memlimit,
)
box = nacl.secret.SecretBox(key)
# test that it works (i.e. that you got the password right)
import base64
test_string = plist["kBackupEncryptionStoreEncryptedTestStringKey"]
def decrypt(c):
[cipher, nonce] = c.split(":")
cipher = base64.b64decode(cipher)
nonce = base64.b64decode(nonce)
return box.decrypt(cipher, nonce)
print('test decrypt', decrypt(test_string))
# decrypt the OTP secrets and print them as URI's
import passlib.totp
[cipher, nonce] = encrypted_otp_string.split(":")
cipher = base64.b64decode(cipher)
nonce = base64.b64decode(nonce)
secret = box.decrypt(cipher, nonce)
otp = passlib.totp.TOTP(key=secret, format="raw")
def get_secret(k):
if 'encryptedOTPString' not in k:
return 'no otp string in this entry'
secret = decrypt(k['encryptedOTPString'])
otp = passlib.totp.TOTP(key=secret, format="raw")
return otp.to_uri(k['displayLabel'], k['serviceName'])
for k in ks:
print(get_secret(k))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment