Skip to content

Instantly share code, notes, and snippets.

@Zegnat Zegnat/
Last active Mar 14, 2019

What would you like to do?
Simple script for accessing the contents of an encrypted andOTP backup.

andOTP Decrypt

Simple script for accessing the contents of an encrypted andOTP backup. As long as Sodium is available this does not require any dependencies outside of PHP.

This was written as a replacement for asmw/andOTP-decrypt, which I found a little annoying to get going and depends on several external packages. (Hold! Was PHP easier than Python here? Oh my!)


To decrypt and write to a JSON file:

./decrypt.php otp_accounts.json.aes > otp_accounts.json

The script will prompt you to enter the password used when making the backup.

As the decoded JSON is written to STDOUT, it can be piped into other applications or scripts as well, potentially keeping your secrets from being written to disk. E.g. using jq to only write out the labels in order of most recently used:

./decrypt.php otp_accounts.json.aes | jq 'sort_by(-.last_used) | [.[].label]'

A more advanced use-case of this would be to automatically generate the otpauth URLs for feeding into a different authenticator application. I started on this but didn’t complete the jq command neccessary. If you end up doing it, let me know! Here is a start:

./decrypt.php otp_accounts.json.aes | jq '.[] | "otpauth://" + (.type | ascii_downcase) + "/" + (.label | @uri) + "?secret=" + .secret + "&algorithm=" + .algorithm'

permission denied: ./decrypt.php

If your command line tells you permission denied, you can either try and run the commands via your PHP executable or try to make the script itself executable:

php decrypt.php otp_accounts.json.aes > otp_accounts.json
chmod +x decrypt.php
#!/usr/bin/env php
declare(strict_types = 1);
fputs(STDERR, "Password: ");
$sttyMode = shell_exec('stty -g');
shell_exec('stty -echo');
$value = trim(fgets(STDIN, 4096));
shell_exec(sprintf('stty %s', $sttyMode));
fputs(STDERR, "\n");
$key = hash('sha256', $value, true);
$input = new SplFileObject($argv[1], 'r');
$nonce = $input->fread(12);
$ciphertext = $input->fread($input->getSize());
$input = null;
$out = sodium_crypto_aead_aes256gcm_decrypt($ciphertext, '', $nonce, $key);
if (false === $out) {
fputs(STDERR, "Could not be decrypted.");
fputs(STDOUT, $out . "\n");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.