~dvshkn/website

5709bec5fff873cbb2f681499c1d30fb532638b5 — David Knight 4 months ago e9b375a main
new post: 2024-02-16-migrating-from-authy-to-aegis.md
1 files changed, 156 insertions(+), 0 deletions(-)

A content/blog/2024-02-16-migrating-from-authy-to-aegis.md
A content/blog/2024-02-16-migrating-from-authy-to-aegis.md => content/blog/2024-02-16-migrating-from-authy-to-aegis.md +156 -0
@@ 0,0 1,156 @@
---
title: "Migrating From Authy to Aegis"
date: 2024-02-16T20:00:00-08:00
draft: false
tags: ["howto"]
---

The smell of enshittification is in the air. Twilio announced that the desktop version of Authy is getting the axe on March 19, and this comes after a significant round of layoffs that Twilio performed at the end of 2023. For this reason it seemed like a ripe time to get my authenticator data out of Authy and into something more stable like Aegis. Based on a pick up in activity on GitHub it seems like I'm not alone in my thinking.

Authy itself does not have an official export feature, but all of the information needed to create a dump of account data from the desktop app is present in the comment thread of [this GitHub gist](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93).

There are a lot of comments in the gist thread, and it can be a chore to go through them all in order to piece together what to do. Consequently I'm documenting here what worked for me, and maybe it will help others get their data out too.

_NOTE: This process was only tested with 6-digit TOTP accounts. Other kinds of accounts might not export correctly._

## Tools Used
* Arch Linux + AUR
* Node.js
* Chromium
* KDE Connect (optional)

# Install Authy From the AUR

Install the `authy` package from the AUR. With this method there isn't any need to use an old version of the package. Version 2.5.0 was the latest as of the time of this writing.

# Run Authy and Login

Start the app normally and login. Close the app once accounts show up.

# Unpack Authy Electron Resources

_This step is based on [@fizzfaldt's comment](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93?permalink_comment_id=4898066#gistcomment-4898066) from the gist thread._

1. Create a temp directory somewhere with normal user permissions. These examples will use `/home/user/temp_authy`.

```
$ mkdir /home/user/temp_authy
```

2. The AUR package installs the contents of the Authy snap to `/opt/authy`. Use `node` to extract the inner resource archive to the temp directory.

```
$ npx @electron/asar /opt/authy/resources/app.asar /home/user/temp_authy
```

# Run Authy With Remote Debugging Enabled

_This step is based on [@fizzfaldt's comment](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93?permalink_comment_id=4898066#gistcomment-4898066) from the gist thread._

Run the commands below to manually start the Authy app with a debugging port open. In older versions this used to be possible without taking the package apart.

```
$ cd /home/user/temp_authy
$ npx electron . --remote-debugging-port=5858 --remote-allow-origins=http://localhost:5858
```

After running the `electron` command the Authy app should open again.

# Open the Debug URL in Chromium

1. Open Chromium and go to `http://localhost:5858`. This should load a very plain looking white page.

2. Click the "Twilio Authy" link. This should load a page with a debugging view of the app and dev tools all ready to go.

3. For the next section it is important to the use the dev tools already present in the web page. These dev tools are setup with access to the Authy application state.

# Dump Application Data Using the Dev Tools Console

_This step is based on [@brenc's comment](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93?permalink_comment_id=4864272#gistcomment-4864272) from the gist thread._

The code snippet in the thread by @brenc dumps information for all accounts in Raivo OTP format. The code shown below is my modified version that dumps account information in Aegis format instead.

1. Copy/paste the code snippet shown below into the dev tools console and run it. This should cause a bunch of JSON output to print to the console. Note that the output contains all of the authenticator secrets and is sensitive!

2. Copy/paste the generated JSON output into a text editor and save it to a file.

```
// Based on https://github.com/LinusU/base32-encode/blob/master/index.js
function hex_to_b32(hex) {
  let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
  let bytes = [];
  for (let i = 0; i < hex.length; i += 2) {
    bytes.push(parseInt(hex.substr(i, 2), 16));
  }
  let bits = 0;
  let value = 0;
  let output = "";
  for (let i = 0; i < bytes.length; i++) {
    value = (value << 8) | bytes[i];
    bits += 8;
    while (bits >= 5) {
      output += alphabet[(value >>> (bits - 5)) & 31];
      bits -= 5;
    }
  }
  if (bits > 0) {
    output += alphabet[(value << (5 - bits)) & 31];
  }
  return output;
}

const items = appManager.getModel().map((i) => {
  let secretSeed = i.secretSeed;
  if (typeof secretSeed == "undefined") {
    secretSeed = i.encryptedSeed;
  }
  // @brenc: All of my Authy accounts have a 20 second period. Not sure why
  //         this was 10.
  const period = i.digits === 7 ? 20 : 30;
  const secret =
    i.markedForDeletion === false ? i.decryptedSeed : hex_to_b32(secretSeed);
  const [issuer, rawName] = i.name.includes(":")
    ? i.name.split(":")
    : ["", i.name];
  const name = [issuer, rawName].filter(Boolean).join(": ");

  return {
    type: "totp",
    // NOTE: Aegis generates a fresh UUID if we skip this property
    // uuid: null,
    name,
    issuer: name,
    icon: null,
    info: {
      secret,
      algo: "SHA1",
      digits: i.digits,
      period: period
    }
  };
});

// Example from https://github.com/beemdevelopment/Aegis/blob/master/app/src/test/resources/com/beemdevelopment/aegis/importers/aegis_plain.json
const aegis_data = {
  version: 1,
  header: {
    slots: null,
    params: null
  },
  db: {
    version: 1,
    entries: items
  }
};

// dumps entries to console in Aegis JSON format
console.log(JSON.stringify(aegis_data, undefined, 4));
```

# Copy JSON File to Phone and Import Into Aegis

The JSON dump file is unencrypted, so use a secure method (like KDE Connect) to copy it to the phone. After it is copied over import the file into Aegis (`Settings > Import & Export > Import from file`). If using the code snippet provided in the previous section select "Aegis" as the import file format.

# Testing

Since none of this process is official it's important to test each imported account. Make sure that each account's TOTP codes being generated in Aegis match the ones being generated in Authy.