Author

Topic: How to export Authy 2FA secret codes to a json (no root) and migrate to Aegis (Read 156 times)

hero member
Activity: 2352
Merit: 588
Bitcoin Casino Est. 2013
I don't use Authy, but I want to express my gratitude because I came across your thread, OP, and learned that 2FA is now enabled on this forum. I know that many have been requesting this for a long time, and I'm pleased that it has finally been implemented. I've also enabled 2FA on my account using Aegis; this will now be my preferred method alongside Google Authenticator. I'm considering whether I should switch completely from Google Authenticator to Aegis or if it's fine to keep both. What do you think?
hero member
Activity: 2464
Merit: 934
I've been using Aegis since few years, and it's been top notch. Especially when you switch the device, just import the file and you are done.   it took some labor in start (back then there was no backup option), to manually write codes from Google authenticator but it was worth it.
legendary
Activity: 2212
Merit: 5622
Non-custodial BTC Wallet
Well, no idea why but after a few tries, the QR codes started working. However, Aegis seems to be a bit more archaic than Authy because for instance, Authy could fetch a few logos depending on the sites we were adding the "FA codes to. Aegis doesn't do any of this. It's not an issue, rather a side note. I'll keep both authenticators for some time, until I'm sure all codes are working. After that, I'll simply delete Authy from my phone!

It is always good to keep backups. Keeping both is still an option. Specially if they are in deferent devices.

Be sure to save the json file you generated somewhere safe, as with it you can just switch back to authy, to aegies or to any other authenticator tool anytime you like
hero member
Activity: 1176
Merit: 647
I rather die on my feet than to live on my knees
In my case, Aegis simply doesn't read the QR codes correctly. Or better, I tried to scan at least 20 QR codes and only one was added successfully.

I had a similar problem with qr code in this forum
I just pasteed the secret and it worked fine. What really matters is the secret.  It is all you need to save the 2fa.

Well, no idea why but after a few tries, the QR codes started working. However, Aegis seems to be a bit more archaic than Authy because for instance, Authy could fetch a few logos depending on the sites we were adding the 2FA codes to. Aegis doesn't do any of this. It's not an issue, rather a side note. I'll keep both authenticators for some time, until I'm sure all codes are working. After that, I'll simply delete Authy from my phone!
legendary
Activity: 2212
Merit: 5622
Non-custodial BTC Wallet
In my case, Aegis simply doesn't read the QR codes correctly. Or better, I tried to scan at least 20 QR codes and only one was added successfully.

I had a similar problem with qr code in this forum
I just pasteed the secret and it worked fine. What really matters is the secret.  It is all you need to save the 2fa.
hero member
Activity: 1176
Merit: 647
I rather die on my feet than to live on my knees
In my case, Aegis simply doesn't read the QR codes correctly. Or better, I tried to scan at least 20 QR codes and only one was added successfully.

All others return the following error message:

An error occurred while trying to read the QR code.
com.beemdevelopment.aegis.otp.GoogleAuthInfoException: Bad secret (java.lang.IllegalArgumentException: com.google.common.io.BaseEncoding$DecodingException: Invalid input length 9)

I'm using Firefox and Authy version2.2.3

Anyone knows why this happens?
legendary
Activity: 2212
Merit: 5622
Non-custodial BTC Wallet
Now that the forum has enabled 2FA, take this opportunity to convert all your logins from authy o aegis!

Aegis is safer than authy,  as your account can never be blocked.

Save all your authy codes in a backup and migrate to aegis.
legendary
Activity: 2170
Merit: 3858
Farewell o_e_l_e_o
As it doesn't allow you to export your keys, it is very hard to migrate to another service, such as Aegis (https://getaegis.app/ free and open source, which I am using now)
A review topic on Aegis Authenticator
That app has feature to import 2FA codes from others too. That's amazing.

Also by the way, if you have a rooted android phone, you can import your 2FA codes from Authy, FreeOTP, Google Authenticator, etc, to Aegis.



Screenshot from their PlayStore page
legendary
Activity: 2212
Merit: 5622
Non-custodial BTC Wallet
Basically everyone here uses some kind of 2FA authenticator to use cryptocurrency exchanges, emails and other services.

While Authy is indeed very handy, as it easily sync across multiple devices, it is terrible for privacy. They request your phone to send SMS as a security measure. They also do not allow you to export your keys easily. You can read more problems about Authy here:

As it doesn't allow you to export your keys, it is very hard to migrate to another service, such as Aegis (https://getaegis.app/ free and open source, which I am using now)

For years I was an Authy user. Until today.  I just learned how to export all your keys in a Json file, and I will share it now.
You don't need a rooted phone, as we will do it in windows (also compatible with linux and mac)

Step by step here https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93

I will make a small summary on windows:



Just install Authy desktop and add a shortcut to your desktop.

Edit the target of the shortcut (in Properties):
Quote
On Windows: right-click the Authy desktop shortcut, and in the Target field write --remote-debugging-port=5858 at the end. Then click OK. Double-click the Authy desktop shortcut.
On Mac: from Terminal.app: open -a "Authy Desktop" --args --remote-debugging-port=5858
On Linux, from a terminal: authy --remote-debugging-port=5858


Open Google Chrome and go to this URL http://localhost:5858
It must be google chrome, it didn't work on Edge in my computer.

Quote
Click the Twilio Authy link in that webpage.
In Chrome Developer Tools top navigation bar, go to Application (if you don't see it, click >> to expand the full list) Then on the left, click Frames → "⃞top" to display contents.
Then right-click main.html and select Open in containing folder. That will open a Console where you can paste the following code:

Code:
// QRious v4.0.2 | (C) 2017 Alasdair Mercer | GPL v3 License Based on jsqrencode | (C) 2010 [email protected] | GPL v3 License
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.QRious=e()}(this,function(){"use strict";function t(t,e){var n;return"function"==typeof Object.create?n=Object.create(t):(s.prototype=t,n=new s,s.prototype=null),e&&i(!0,n,e),n}function e(e,n,s,r){var o=this;return"string"!=typeof e&&(r=s,s=n,n=e,e=null),"function"!=typeof n&&(r=s,s=n,n=function(){return o.apply(this,arguments)}),i(!1,n,o,r),n.prototype=t(o.prototype,s),n.prototype.constructor=n,n.class_=e||o.class_,n.super_=o,n}function i(t,e,i){for(var n,s,a=0,h=(i=o.call(arguments,2)).length;a>1&1,n=0;n0;e--)n[e]=n[e]?n[e-1]^_.EXPONENT[v._modN(_.LOG[n[e]]+t)]:n[e-1];n[0]=_.EXPONENT[v._modN(_.LOG[n[0]]+t)]}for(t=0;t<=i;t++)n[t]=_.LOG[n[t]]},_checkBadness:function(){var t,e,i,n,s,r=0,o=this._badness,a=this.buffer,h=this.width;for(s=0;sh*h;)u-=h*h,c++;for(r+=c*v.N4,n=0;n=o-2&&(t=o-2,s>9&&t--);var a=t;if(s>9){for(r[a+2]=0,r[a+3]=0;a--;)e=r[a],r[a+3]|=255&e<<4,r[a+2]=e>>4;r[2]|=255&t<<4,r[1]=t>>4,r[0]=64|t>>12}else{for(r[a+1]=0,r[a+2]=0;a--;)e=r[a],r[a+2]|=255&e<<4,r[a+1]=e>>4;r[1]|=255&t<<4,r[0]=64|t>>4}for(a=t+3-(s<10);a=5&&(i+=v.N1+n[e]-5);for(e=3;et||3*n[e-3]>=4*n[e]||3*n[e+3]>=4*n[e])&&(i+=v.N3);return i},_finish:function(){this._stringBuffer=this.buffer.slice();var t,e,i=0,n=3e4;for(e=0;e<8&&(this._applyMask(e),(t=this._checkBadness())>=1)1&n&&(s[r-1-e+8*r]=1,e<6?s[8+r*e]=1:s[8+r*(e+1)]=1);for(e=0;e<7;e++,n>>=1)1&n&&(s[8+r*(r-7+e)]=1,e?s[6-e+8*r]=1:s[7+8*r]=1)},_interleaveBlocks:function(){var t,e,i=this._dataBlock,n=this._ecc,s=this._eccBlock,r=0,o=this._calculateMaxLength(),a=this._neccBlock1,h=this._neccBlock2,f=this._stringBuffer;for(t=0;t1)for(t=u.BLOCK[n],i=s-7;;){for(e=s-7;e>t-3&&(this._addAlignment(e,i),!(e6)for(t=d.BLOCK[r-7],e=17,i=0;i<6;i++)for(n=0;n<3;n++,e--)1&(e>11?r>>e-12:t>>e)?(s[5-i+o*(2-n+o-11)]=1,s[2-n+o-11+o*(5-i)]=1):(this._setMask(5-i,2-n+o-11),this._setMask(2-n+o-11,5-i))},_isMasked:function(t,e){var i=v._getMaskBit(t,e);return 1===this._mask[i]},_pack:function(){var t,e,i,n=1,s=1,r=this.width,o=r-1,a=r-1,h=(this._dataBlock+this._eccBlock)*(this._neccBlock1+this._neccBlock2)+this._neccBlock2;for(e=0;ee&&(i=t,t=e,e=i),i=e,i+=e*e,i>>=1,i+=t},_modN:function(t){for(;t>=255;)t=((t-=255)>>8)+(255&t);return t},N1:3,N2:3,N3:40,N4:10}),p=v,m=f.extend({draw:function(){this.element.src=this.qrious.toDataURL()},reset:function(){this.element.src=""},resize:function(){var t=this.element;t.width=t.height=this.qrious.size}}),g=h.extend(function(t,e,i,n){this.name=t,this.modifiable=Boolean(e),this.defaultValue=i,this._valueTransformer=n},{transform:function(t){var e=this._valueTransformer;return"function"==typeof e?e(t,this):t}}),k=h.extend(null,{abs:function(t){return null!=t?Math.abs(t):null},hasOwn:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},noop:function(){},toUpperCase:function(t){return null!=t?t.toUpperCase():null}}),w=h.extend(function(t){this.options={},t.forEach(function(t){this.options[t.name]=t},this)},{exists:function(t){return null!=this.options[t]},get:function(t,e){return w._get(this.options[t],e)},getAll:function(t){var e,i=this.options,n={};for(e in i)k.hasOwn(i,e)&&(n[e]=w._get(i[e],t));return n},init:function(t,e,i){"function"!=typeof i&&(i=k.noop);var n,s;for(n in this.options)k.hasOwn(this.options,n)&&(s=this.options[n],w._set(s,s.defaultValue,e),w._createAccessor(s,e,i));this._setAll(t,e,!0)},set:function(t,e,i){return this._set(t,e,i)},setAll:function(t,e){return this._setAll(t,e)},_set:function(t,e,i,n){var s=this.options[t];if(!s)throw new Error("Invalid option: "+t);if(!s.modifiable&&!n)throw new Error("Option cannot be modified: "+t);return w._set(s,e,i)},_setAll:function(t,e,i){if(!t)return!1;var n,s=!1;for(n in t)k.hasOwn(t,n)&&this._set(n,t[n],e,i)&&(s=!0);return s}},{_createAccessor:function(t,e,i){var n={get:function(){return w._get(t,e)}};t.modifiable&&(n.set=function(n){w._set(t,n,e)&&i(n,t)}),Object.defineProperty(e,t.name,n)},_get:function(t,e){return e["_"+t.name]},_set:function(t,e,i){var n="_"+t.name,s=i[n],r=t.transform(null!=e?e:t.defaultValue);return i[n]=r,r!==s}}),M=w,b=h.extend(function(){this._services={}},{getService:function(t){var e=this._services[t];if(!e)throw new Error("Service is not being managed with name: "+t);return e},setService:function(t,e){if(this._services[t])throw new Error("Service is already managed with name: "+t);e&&(this._services[t]=e)}}),B=new M([new g("background",!0,"white"),new g("backgroundAlpha",!0,1,k.abs),new g("element"),new g("foreground",!0,"black"),new g("foregroundAlpha",!0,1,k.abs),new g("level",!0,"L",k.toUpperCase),new g("mime",!0,"image/png"),new g("padding",!0,null,k.abs),new g("size",!0,100,k.abs),new g("value",!0,"")]),y=new b,O=h.extend(function(t){B.init(t,this,this.update.bind(this));var e=B.get("element",this),i=y.getService("element"),n=e&&i.isCanvas(e)?e:i.createCanvas(),s=e&&i.isImage(e)?e:i.createImage();this._canvasRenderer=new c(this,n,!0),this._imageRenderer=new m(this,s,s===e),this.update()},{get:function(){return B.getAll(this)},set:function(t){B.setAll(t,this)&&this.update()},toDataURL:function(t){return this.canvas.toDataURL(t||this.mime)},update:function(){var t=new p({level:this.level,value:this.value});this._canvasRenderer.render(t),this._imageRenderer.render(t)}},{use:function(t){y.setService(t.getName(),t)}});Object.defineProperties(O.prototype,{canvas:{get:function(){return this._canvasRenderer.getElement()}},image:{get:function(){return this._imageRenderer.getElement()}}});var A=O,L=h.extend({getName:function(){}}).extend({createCanvas:function(){},createImage:function(){},getName:function(){return"element"},isCanvas:function(t){},isImage:function(t){}}).extend({createCanvas:function(){return document.createElement("canvas")},createImage:function(){return document.createElement("img")},isCanvas:function(t){return t instanceof HTMLCanvasElement},isImage:function(t){return t instanceof HTMLImageElement}});return A.use(new L),A});

// 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; }

// Based on https://github.com/adriancooney/console.image
function console_image(url, size) { console.log("%c+", "font-size: 1px; padding: " + Math.floor(size / 2) + "px " + Math.floor(size / 2) + "px; line-height: " + size + "px; background: url(" + url + "); color: transparent;"); }

(function(console) { console.save = function(data, filename) { if (!data) { console.error('Console.save: No data'); return; } if (typeof data === "object") { data = JSON.stringify(data, undefined, 4) } var blob = new Blob([data], {type: 'text/json'}), e = document.createEvent('MouseEvents'), a = document.createElement('a'); a.download = filename; a.href = window.URL.createObjectURL(blob); a.dataset.downloadurl =  ['text/json', a.download, a.href].join(':'); e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); a.dispatchEvent(e); } })(console);

console.warn("Here's your Authy tokens:");
var data = appManager.getModel().map(function(i) {
var secretSeed = i.secretSeed;
if (typeof secretSeed == 'undefined') {
   secretSeed = i.encryptedSeed;
}
var secret = (i.markedForDeletion === false ? i.decryptedSeed : hex_to_b32(secretSeed));
var period = (i.digits === 7 ? 10 : 30);
var totp_uri = `otpauth://totp/${encodeURIComponent(i.name)}?secret=${secret}&digits=${i.digits}&period=${period}`;
console.group(i.name); console.log('TOTP secret:', secret); console.log('TOTP URI:', totp_uri); var qr_size = 250; var url = (new QRious({value: totp_uri, size: qr_size})).toDataURL(); console_image(url, qr_size); console.groupEnd();
return {name: i.name, secret: secret, uri: totp_uri};
});
//console.save(data, 'authy_backup.json');

You will see all your keys in QR codes in your console.

you can just scan all of them with aegis.

Or, you can just remove "//" in the last line to download a file called 'authy_backup.json', with all your codes and easily import it into any other good 2FA software.



I hope this helps you too, to migrate to a better software with more privacy and freedom.
Jump to: