feat: added google migration support (BETA) v.1.2.0
This commit is contained in:
parent
fb6ece773c
commit
21c7646c71
13
README.md
13
README.md
@ -1,6 +1,17 @@
|
|||||||
# TOTPFIT
|
# TOTPFIT
|
||||||
### Another 2FAuthenticator based on TOTP for Zepp Amazfit GTS 4
|
### Another 2FAuthenticator based on TOTP for Zepp Amazfit GTS 4
|
||||||
|
|
||||||
Features:
|

|
||||||
|
|
||||||
|
### Features:
|
||||||
- Supports of otpauth links with parameters "issuer", "algorithm", "digits", "period"
|
- Supports of otpauth links with parameters "issuer", "algorithm", "digits", "period"
|
||||||
- Addition/Edition/Deletion of TOTPs from mobile settings app
|
- Addition/Edition/Deletion of TOTPs from mobile settings app
|
||||||
|
|
||||||
|
### Google Migration Support:
|
||||||
|
- Support of google migration links formated: ```otpauth-migration://offline?data=...``` (BETA)
|
||||||
|
|
||||||
|
### Screenshots:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
BIN
docs/assets/image.png
Normal file
BIN
docs/assets/image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
docs/assets/image2.png
Normal file
BIN
docs/assets/image2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
@ -9,7 +9,6 @@ export function decodeVarint(buffer, offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte = buffer[offset++];
|
byte = buffer[offset++];
|
||||||
console.log(this)
|
|
||||||
|
|
||||||
const multiplier = this.BigInt(2) ** this.BigInt(shift);
|
const multiplier = this.BigInt(2) ** this.BigInt(shift);
|
||||||
const thisByteValue = this.BigInt(byte & 0x7f) * multiplier;
|
const thisByteValue = this.BigInt(byte & 0x7f) * multiplier;
|
||||||
|
@ -25,6 +25,32 @@ function leftpad(str, len, pad) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function encode(bytes) {
|
||||||
|
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
|
||||||
|
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)) & 0x1F];
|
||||||
|
bits -= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits > 0) {
|
||||||
|
output += alphabet[(value << (5 - bits)) & 0x1F];
|
||||||
|
}
|
||||||
|
|
||||||
|
const paddingLength = (8 - (output.length % 8)) % 8;
|
||||||
|
output += '='.repeat(paddingLength);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
export function base64decode(base64) {
|
export function base64decode(base64) {
|
||||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
let result = [];
|
let result = [];
|
||||||
|
@ -6,7 +6,6 @@ import { LocalStorage } from "@zos/storage";
|
|||||||
const app = getApp();
|
const app = getApp();
|
||||||
|
|
||||||
let waitForFetch = true;
|
let waitForFetch = true;
|
||||||
let localStorage = new LocalStorage();
|
|
||||||
|
|
||||||
Page(
|
Page(
|
||||||
BasePage({
|
BasePage({
|
||||||
@ -14,6 +13,8 @@ Page(
|
|||||||
this.getTOTPData()
|
this.getTOTPData()
|
||||||
.then((x) => {
|
.then((x) => {
|
||||||
app._options.globalData.TOTPS = JSON.parse(x) ?? [];
|
app._options.globalData.TOTPS = JSON.parse(x) ?? [];
|
||||||
|
|
||||||
|
let localStorage = new LocalStorage();
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TOTPs",
|
"TOTPs",
|
||||||
JSON.stringify(app._options.globalData.TOTPS)
|
JSON.stringify(app._options.globalData.TOTPS)
|
||||||
@ -22,6 +23,7 @@ Page(
|
|||||||
})
|
})
|
||||||
.catch((x) => {
|
.catch((x) => {
|
||||||
console.log(`Init failed: ${x}`);
|
console.log(`Init failed: ${x}`);
|
||||||
|
let localStorage = new LocalStorage();
|
||||||
app._options.globalData.TOTPS = JSON.parse(
|
app._options.globalData.TOTPS = JSON.parse(
|
||||||
localStorage.getItem("TOTPs", null) ?? []
|
localStorage.getItem("TOTPs", null) ?? []
|
||||||
);
|
);
|
||||||
|
@ -13,12 +13,16 @@ AppSettingsPage({
|
|||||||
placeholder: "otpauth://",
|
placeholder: "otpauth://",
|
||||||
label: "Add new OTP Link",
|
label: "Add new OTP Link",
|
||||||
onChange: (changes) => {
|
onChange: (changes) => {
|
||||||
var link = getTOTPByLink(changes);
|
let link = getTOTPByLink(changes);
|
||||||
if (link == null) {
|
if (link == null) {
|
||||||
console.log("link is invalid");
|
console.log("link is invalid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
storage.push(link);
|
|
||||||
|
if(Array.isArray(link))
|
||||||
|
storage.push(...link);
|
||||||
|
else storage.push(link);
|
||||||
|
|
||||||
updateStorage(storage);
|
updateStorage(storage);
|
||||||
},
|
},
|
||||||
labelStyle: {
|
labelStyle: {
|
||||||
@ -80,7 +84,11 @@ function GetTOTPList(storage) {
|
|||||||
label: "Change OTP link",
|
label: "Change OTP link",
|
||||||
onChange: (changes) => {
|
onChange: (changes) => {
|
||||||
try {
|
try {
|
||||||
storage[elementId] = getTOTPByLink(changes);
|
let link = getTOTPByLink(changes);
|
||||||
|
if(Array.isArray(link))
|
||||||
|
return;
|
||||||
|
|
||||||
|
storage[elementId] = link;
|
||||||
updateStorage(storage);
|
updateStorage(storage);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { decodeProto } from "../../lib/protobuf-decoder/protobufDecoder";
|
import { decodeProto, TYPES } from "../../lib/protobuf-decoder/protobufDecoder";
|
||||||
import { TOTP } from "../../lib/totp-quickjs";
|
import { TOTP } from "../../lib/totp-quickjs";
|
||||||
import { base64decode } from "../../lib/totp-quickjs/base32decoder";
|
import { base64decode, encode } from "../../lib/totp-quickjs/base32decoder";
|
||||||
|
|
||||||
const otpauthScheme = "otpauth:/";
|
const otpauthScheme = "otpauth:/";
|
||||||
const googleMigrationScheme = "otpauth-migration:/";
|
const googleMigrationScheme = "otpauth-migration:/";
|
||||||
@ -40,7 +40,7 @@ function getByOtpauthScheme(link){
|
|||||||
if (secret === undefined) throw new Error("Secret not defined");
|
if (secret === undefined) throw new Error("Secret not defined");
|
||||||
|
|
||||||
if(issuer == client){
|
if(issuer == client){
|
||||||
issuer = args[3].split("issuer=")[1]?.split("&")[0]
|
issuer = args[3].split("issuer=")[1]?.split("&")[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
issuer = decodeURIComponent(issuer);
|
issuer = decodeURIComponent(issuer);
|
||||||
@ -65,9 +65,49 @@ function getByGoogleMigrationScheme(link){
|
|||||||
|
|
||||||
let data = link.split("data=")[1]; //Returns base64 encoded data
|
let data = link.split("data=")[1]; //Returns base64 encoded data
|
||||||
data = decodeURIComponent(data);
|
data = decodeURIComponent(data);
|
||||||
console.log(data)
|
|
||||||
let decode = base64decode(data);
|
let decode = base64decode(data);
|
||||||
console.log(decode)
|
|
||||||
let proto = decodeProto(decode);
|
let proto = decodeProto(decode);
|
||||||
console.log(proto);
|
|
||||||
|
let protoTotps = [];
|
||||||
|
|
||||||
|
proto.parts.forEach(part => {
|
||||||
|
if(part.type == TYPES.LENDELIM){
|
||||||
|
protoTotps.push(decodeProto(part.value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let totps = [];
|
||||||
|
protoTotps.forEach(x => {
|
||||||
|
let type = x.parts.filter(x => x.index == 6)[0]; //find type of OTP
|
||||||
|
if(type.value !== '2'){
|
||||||
|
console.log("ERR: it's a not TOTP record")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let secret = x.parts.filter(x => x.index == 1)[0].value;
|
||||||
|
secret = encode(secret);
|
||||||
|
|
||||||
|
let name = bytesToString(x.parts.filter(x => x.index == 2)[0].value);
|
||||||
|
let issuer = bytesToString(x.parts.filter(x => x.index == 3)[0].value);
|
||||||
|
|
||||||
|
totps.push(new TOTP(
|
||||||
|
secret,
|
||||||
|
issuer,
|
||||||
|
name,
|
||||||
|
6,
|
||||||
|
30,
|
||||||
|
0,
|
||||||
|
"SHA-1"
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
return totps;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function bytesToString(bytes) {
|
||||||
|
let str = '';
|
||||||
|
for (let i = 0; i < bytes.length; i++) {
|
||||||
|
str += String.fromCharCode(bytes[i]);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user