Skip to content

Instantly share code, notes, and snippets.

@pigsflew
Forked from Ingramz/AuthyToOtherAuthenticator.md
Last active June 25, 2019 02:24
Show Gist options
  • Save pigsflew/8f5b338af9f2890c0ebe4a12c1775602 to your computer and use it in GitHub Desktop.
Save pigsflew/8f5b338af9f2890c0ebe4a12c1775602 to your computer and use it in GitHub Desktop.

Generating Authy passwords on other authenticators


There is an increasing count of applications which use Authy for two-factor authentication. However many users who aren't using Authy, have their own authenticator setup up already and do not wish to use two applications for generating passwords.

Since I use 1Password for all of my password storing/generating needs, I was looking for a solution to use Authy passwords on that. I couldn't find any completely working solutions, however I stumbled upon a gist by Brian Hartvigsen. His post had a neat code with it to generate QR codes (beware, through Google) for you to use on your favorite authenticator.

His method is to extract the secret keys using Authy's Google Chrome app via Developer Tools. If this was not possible, I guess people would be reverse engineering the Android app or something like that. But when I tried that code, nothing appeared on the screen. My guess is that Brian used the code to extract the keys that weren't necessarily tied to Authy.

I had to adapt the code a little and you can see the result below, but here's what I discovered about Authy's method:

  • They use the exact same algorithm to generate passwords as Google Authenticator and similar (TOTP)
  • The passwords are one digit longer - 7 digits (usually they're 6, with exceptions), but if you've looked at one of the Authy generated passwords already, you probably noticed it too
  • The password validity period is 10 seconds (instead of usual 30). Authy shows 20 seconds, but that means a slightly different thing. Don't substitute this period longer in your Authenticator.
  • Authy's secret keys are in hex already, so they need to be turned back to base32 for working QR codes

So as long as you have an authenticator which can do longer passwords than 6 characters and do custom time periods, then congratulations, you can use the following method. If you are not sure, scan this code with your authenticator to test. Don't forget to delete it afterwards. The code should have 7 digits and should change every 10 seconds.

Example QR Code

Known to work:

  • 1Password for OS X
  • 1Password for iOS
  • Google Authenticator

Known not to work:

  • 1Password for Windows (doesn't support other digit counts and timeouts yet)
  • Authy for iOS (doesn't support other timeouts than 30s, the irony!)

Ok, that's nice, but I want to get rid of Authy now

This method has only one gotcha - if you want add a new service that relies on Authy, you will need to run Authy again. I am assuming you know how to use Authy and have some services added already. You can probably get rid of Authy on your phone and log in to Authy on your Chrome app using SMS or keep it permanently disabled under your extensions once you have logged in. In that case set a master password for Authy, stay secure.

  1. Install Authy from Chrome Web Store
  2. Open Authy and log in, so you can see the codes being generated for you
  3. Go to Extensions page in your browser (chrome://extensions/ or Menu -> More tools -> Extensions)
  4. Tick developer mode in top right corner
  5. Find "Authy" (not "Authy Chrome Extension", both will be installed) from the list and then click on main.html.
  6. Chrome developer tools with Console selected should open. If it didn't, go to Console tab.
  7. Paste following and press enter:
var b64encode = window.AWS.util.base64.encode;
var out={};html=""
appManager.getModel().forEach(function(i) {
var secret=(i.markedForDeletion === false ? i.decryptedSeed : b64encode(i.secretSeed));
var uri=`otpauth://totp/${encodeURIComponent(i.name)}?secret=${secret}&issuer=${i.accountType}&digits=${i.digits}`;
var qr=`https://www.google.com/chart?chs=100x100&chld=L|0&cht=qr&chl=${encodeURIComponent(uri)}`;
out[i.name]={secret, uri, qr}; html+=`<tr><td><webview class="qr" src="${qr}" allowtransparency></iframe></td><td><dt>${i.name}</dt><dd><a target="_blank" href="${uri}">${uri}</a></dd></td></tr>`;
});var w;var d;
chrome.app.window.create("img/search_icon.png",{},(wi)=>{w=wi.contentWindow;w.onload=()=>{d=w.document;
d.children[0].innerHTML='';
d.head.innerHTML='<title>Authy Codes</title><style>html{overflow-y:visible;background:#ccc}body{margin:.5em}h1{text-align:center}dt{margin-bottom:.5em;font-weight:bold}.qr{display:inline-block;width:100px;height:100px}</style>';
d.body.innerHTML=`<h1>Authy Codes</h1><table><colgroup><col width="100"><col style="align-content:top"></colgroup>${html}</table>`;
}});
console.table(out, ["secret"]);
  1. A page should open with QR codes for all of your entries, scan them in!
  2. Close opened window and developer tools.
  3. Disable Authy app on Chrome or remove it
  4. Disable Developer mode

Resources used for getting correct codes

Other notes

  • I am not responsible for your actions.
  • I am sure someone has already discovered everything I wrote before, but I couldn't find anything written about it in detail, I didn't invent anything new here
  • The code is a horrible hack, it works for what it does and that's the important bit, improvements are welcome
  • If anyone from Authy reads this - security shouldn't rely on obfuscation or hiding of any sort and should take advantage of freedom of choice where possible. I love the idea of the keys being tied to ones phone number and making this system easy to use for everyone, but please make these URI-s exportable to other applications if users wish to do so - it's possible as demonstrated above and you probably know it. Transparency is what makes this system secure. If you don't wish to do that, then please don't break this method of acquiring keys.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment