kachick / dotfiles

🤤✂🌳
MIT License
13 stars 0 forks source link

Replace Authy with something in the TOTP MFA toolkit #399

Closed kachick closed 9 months ago

kachick commented 9 months ago

Why

https://help.twilio.com/articles/22771146070299-End-user-guide-End-of-Life-EOL-for-Twilio-Authy-Desktop-app https://support.authy.com/hc/en-us/articles/17592416719003-Business-customer-guide-End-of-Life-EOL-for-use-of-Authy-API-with-Twilio-Authy-Desktop-apps

How

https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93

kachick commented 9 months ago

Worked solutions

Export To Bitwarden https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93?permalink_comment_id=4864272#file-authytootherauthenticator-md ```javascript // 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; } // from https://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid#answer-2117523 function uuidv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } // from https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93 function saveToFile(data, filename) { if (!data) { console.error('Console.save: No data'); return; } if (typeof data === "object") { data = JSON.stringify(data, undefined, 4) } const blob = new Blob([data], { type: 'text/json' }); const e = document.createEvent('MouseEvents'); const 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); } function deEncrypt({ log = false, save = false }) { const folder = { id: uuidv4(), name: 'Imported from Authy' }; const bw = { "encrypted": false, "folders": [ folder ], "items": appManager.getModel().map((i) => { let secretSeed = i.secretSeed; if (typeof secretSeed == "undefined") { secretSeed = i.encryptedSeed; } const secret = (i.markedForDeletion === false ? i.decryptedSeed : hex_to_b32(secretSeed)); const period = (i.digits === 7 ? 10 : 30); const [issuer, rawName] = (i.name.includes(":")) ? i.name.split(":") : ["", i.name]; const name = [issuer, rawName].filter(Boolean).join(": "); const totp = `otpauth://totp/${name}?secret=${secret}&digits=${i.digits}&period=${period}${issuer ? '&issuer=' + issuer : ''}`; return ({ id: uuidv4(), organizationId: null, folderId: folder.id, type: 1, reprompt: 0, name, notes: null, favorite: false, login: { username: null, password: null, totp }, collectionIds: null }); }), }; if (log) console.log(JSON.stringify(bw)); if (save) saveToFile(bw, 'authy-to-bitwarden-export.json'); } deEncrypt({ log: true, save: true, }); ```
Export to 2FAS via Ravio format https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93?permalink_comment_id=4864272#gistcomment-4864272 ```javascript // 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; } // from https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93 function saveToFile(data, filename) { if (!data) { console.error("Console.save: No data"); return; } if (typeof data === "object") { data = JSON.stringify(data, undefined, 4); } const blob = new Blob([data], { type: "text/json", }); const e = document.createEvent("MouseEvents"); const 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); } const items = appManager.getModel().map((i) => { let secretSeed = i.secretSeed; if (typeof secretSeed == "undefined") { secretSeed = i.encryptedSeed; } // 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 { account: name, algorithm: "SHA1", counter: "0", digits: `${i.digits}`, iconType: "", iconValue: "", issuer: name, kind: "TOTP", pinned: "false", secret, timer: `${period}`, }; }); saveToFile(items, "Authy-To-Raivo-OTP-Export.json"); ```

Much helped me, thank you 🙏