Skip to content

Commit

Permalink
improve: check key is valid or not before pass it to OTP
Browse files Browse the repository at this point in the history
  • Loading branch information
KawaiiZapic committed Apr 15, 2024
1 parent 8fa936c commit 1c25ece
Showing 1 changed file with 119 additions and 75 deletions.
194 changes: 119 additions & 75 deletions Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,60 +48,94 @@ public Main() {

public List<Result> Query(Query query) {
if (query.Search.StartsWith("otpauth://totp/")) {
var list = new List<Result>();
try {
var link = new Uri(query.Search);
var name = link.LocalPath.ToString()[1..];
var queries = HttpUtility.ParseQueryString(link.Query);
var sercet = queries.Get("secret") ?? throw new Exception();
list.Add(new Result {
Title = name,
SubTitle = "Add to list",
IcoPath = IconAdd,
Action = (e) => {
_list.Entries.Add(new OTPList.KeyEntry {
Key = EncryptKey(sercet),
Name = name,
IsEncrypted = true
});
_storage.Save();
return HandleNormalOtpImport(query.Search);
}
if (query.Search.StartsWith("otpauth-migration://offline?")) {
return HandleGoogleAuthImport(query.Search);
}

var result = new List<Result>();

_list.Entries.ForEach(totp => {
if (query.Search.Length != 0 && !StringMatcher.FuzzySearch(query.Search, totp.Name).Success)
return;
var key = totp.Key;
if (totp.IsEncrypted) {
key = DecryptKey(key);
}
if (!CheckKeyValid(key)) {
result.Add(new Result {
Title = totp.Name + ": Invalid OTP secret",
SubTitle = "This OTP contains a invalid OTP secret that can't be decode as base32 data",
IcoPath = IconWarn,
Action = (e) => {
return false;
}
});
} else {
var totpInst = new Totp(Base32Encoding.ToBytes(key));
result.Add(new Result {
Title = totpInst.ComputeTotp() + " - " + totp.Name,
SubTitle = "Copy to clipboard - Expired in " + totpInst.RemainingSeconds().ToString() + "s",
IcoPath = IconCopy,
Action = (e) => {
Clipboard.SetText(totpInst.ComputeTotp());
return true;
}
});
} catch (Exception) {
list.Add(new Result {
Title = "Invaild otpauth link",
SubTitle = "Check your link or try to copy it again",
}
});
if (result.Count == 0 && query.RawQuery.StartsWith(query.ActionKeyword)) {
if (_list.Entries.Count == 0) {
result.Add(new Result {
Title = "No TOTP found in config",
SubTitle = "Add TOTP to plugin by paste your setup link(otpauth://) first",
IcoPath = IconWarn,
Action = (e) => {
return false;
}
});
} else {
result.Add(new Result {
Title = "No matching result",
SubTitle = "Leave it blank to show all items",
IcoPath = IconWarn,
Action = (e) => {
return false;
}
});
}
return list;
}
if (query.Search.StartsWith("otpauth-migration://offline?")) {
try {
var uri = new Uri(query.Search);
var queries = HttpUtility.ParseQueryString(uri.Query);
var payload = queries.Get("data") ?? throw new Exception();
var decoded = Payload.Parser.ParseFrom(Convert.FromBase64String(payload));

return new List<Result> {
new Result {
Title = "Add " + decoded.OtpParameters.Count() + " items to list",
return result;
}
public List<Result> HandleGoogleAuthImport(string url) {
try {
var uri = new Uri(url);
var queries = HttpUtility.ParseQueryString(uri.Query);
var payload = queries.Get("data") ?? throw new Exception();
var decoded = Payload.Parser.ParseFrom(Convert.FromBase64String(payload));

return new List<Result> {
new() {
Title = "Add " + decoded.OtpParameters.Count + " items to list",
SubTitle = "From Google Authenticator App, batch " + (decoded.BatchIndex + 1).ToString() + " / " + decoded.BatchSize,
IcoPath = IconAdd,
Action = (e) => {
foreach (var item in decoded.OtpParameters) {
var key = Base32Encoding.ToString(item.Secret.ToByteArray());
var name = "";
if (item.Issuer.Length == 0) {
name = item.Name;
} else if (item.Name.Length == 0) {
name = item.Issuer + ": <NO NAME>";
var name = item.Issuer;
if (item.Name.Length > 0) {
if (name.Length > 0) {
name += ": " + item.Name;
} else {
name = item.Name;
}
} else {
name = item.Issuer + ": " + item.Name;
if (name.Length > 0) {
name += ": <NO NAME>";
} else {
name = "<NO NAME>";
}
}
_list.Entries.Add(new OTPList.KeyEntry{
Name = name,
Expand All @@ -114,62 +148,72 @@ public List<Result> Query(Query query) {
}
}
};
} catch (Exception) {
return new List<Result> {
new Result {
Title = "Invaild otpauth-migration link",
} catch (Exception) {
return new List<Result> {
new () {
Title = "Invalid otpauth-migration link",
SubTitle = "Check your link or try to copy it again",
IcoPath = IconWarn,
Action = (e) => {
return false;
}
}
};
}
}

var result = new List<Result>();

_list.Entries.ForEach(totp => {
if (query.Search.Length != 0 && !StringMatcher.FuzzySearch(query.Search, totp.Name).Success)
return;
var key = totp.Key;
if (totp.IsEncrypted) {
key = DecryptKey(key);
}
var totpInst = new Totp(Base32Encoding.ToBytes(key));
result.Add(new Result {
Title = totpInst.ComputeTotp() + " - " + totp.Name,
SubTitle = "Copy to clipboard - Expired in " + totpInst.RemainingSeconds().ToString() + "s",
IcoPath = IconCopy,
Action = (e) => {
Clipboard.SetText(totpInst.ComputeTotp());
return true;
}
});
});
if (result.Count == 0 && query.RawQuery.StartsWith(query.ActionKeyword)) {
if (_list.Entries.Count == 0) {
result.Add(new Result {
Title = "No TOTP found in config",
SubTitle = "Add TOTP to plugin by paste your setup link(otpauth://) first",
}
public List<Result> HandleNormalOtpImport(string url) {
var list = new List<Result>();
try {
var link = new Uri(url);
var name = link.LocalPath.ToString()[1..];
var queries = HttpUtility.ParseQueryString(link.Query);
var sercet = queries.Get("secret") ?? throw new Exception();
if (!CheckKeyValid(sercet)) {
list.Add(new Result {
Title = "Invalid OTP secret",
SubTitle = "This link contains a invalid OTP secret that can't be decode as base32 data",
IcoPath = IconWarn,
Action = (e) => {
return false;
}
});

} else {
result.Add(new Result {
Title = "No matching result",
SubTitle = "Leave it blank to show all items",
IcoPath = IconWarn,
list.Add(new Result {
Title = name,
SubTitle = "Add to list",
IcoPath = IconAdd,
Action = (e) => {
return false;
_list.Entries.Add(new OTPList.KeyEntry {
Key = EncryptKey(sercet),
Name = name,
IsEncrypted = true
});
_storage.Save();
return true;
}
});
}
} catch (Exception) {
list.Add(new Result {
Title = "Invalid otpauth link",
SubTitle = "Check your link or try to copy it again",
IcoPath = IconWarn,
Action = (e) => {
return false;
}
});
}
return list;
}

public static bool CheckKeyValid(string key) {
try {
Base32Encoding.ToBytes(key);
return true;
} catch (Exception) {
return false;
}
return result;
}

public void Init(PluginInitContext context) {
Expand Down

0 comments on commit 1c25ece

Please sign in to comment.