Support for multiple OTP secrets per 1P-record.
This commit is contained in:
parent
90fc1e3d24
commit
4bf76d1b30
@ -88,6 +88,11 @@ for item in opif:
|
||||
# Tags
|
||||
kp.set_tags(item.get_tags())
|
||||
|
||||
# TOTP
|
||||
totps = item.get_totps()
|
||||
if totps:
|
||||
for totp in totps:
|
||||
kp.add_totp(totp[0], title=totp[1])
|
||||
|
||||
|
||||
|
||||
@ -110,10 +115,6 @@ for item in opif:
|
||||
if new_password:
|
||||
entry.password = new_password
|
||||
|
||||
# TOTP
|
||||
totp = item.get_totp()
|
||||
if totp:
|
||||
kp.add_totp(totp)
|
||||
|
||||
# Other web fields
|
||||
if "fields" in secure:
|
||||
|
17
kpwriter.py
17
kpwriter.py
@ -32,12 +32,21 @@ class KpWriter:
|
||||
def set_tags(self, tag_list):
|
||||
self.current_entry.tags = tag_list
|
||||
|
||||
def add_totp(self, init_string, otp_url=None):
|
||||
def add_totp(self, init_string, otp_url=None, title=""):
|
||||
if not otp_url:
|
||||
otp_url = "otpauth://totp/Sample:username?secret={}&algorithm=SHA1&digits=6&period=30&issuer=Sample".format(quote_plus(init_string))
|
||||
# TODO: Support multiple / don't overwrite
|
||||
self.set_prop("TimeOtp-Secret-Base32", init_string, True)
|
||||
self.set_prop("otp", otp_url)
|
||||
|
||||
# It's possible to define multiple OTP-secrets in 1P7, so let's not lose one
|
||||
suffix = ""
|
||||
suffix_ctr = 1
|
||||
while self.current_entry.get_custom_property("otp{}".format(suffix)):
|
||||
suffix_ctr += 1
|
||||
suffix = "_{}".format(suffix_ctr)
|
||||
|
||||
self.set_prop("TimeOtp-Secret-Base32{}".format(suffix), init_string, True)
|
||||
self.set_prop("otp{}".format(suffix), otp_url)
|
||||
if len(title) > 0:
|
||||
self.set_prop("otp_title{}".format(suffix), title)
|
||||
|
||||
def set_prop(self, key, value, protected=False):
|
||||
self.current_entry.set_custom_property(key, value)
|
||||
|
@ -41,15 +41,21 @@ class OnepifEntry():
|
||||
return []
|
||||
return self.raw["openContents"]["tags"]
|
||||
|
||||
def get_totp(self):
|
||||
def get_totps(self):
|
||||
totp_fields = []
|
||||
if "sections" in self.raw["secureContents"]:
|
||||
for section in self.raw["secureContents"]["sections"]:
|
||||
if "fields" not in section:
|
||||
continue
|
||||
for field in section["fields"]:
|
||||
if field["n"][:5] == "TOTP_":
|
||||
return field["v"]
|
||||
return None
|
||||
totp_fields.append([
|
||||
field["v"],
|
||||
field["t"], # Custom title, if set (isn't displayed in 1P)
|
||||
])
|
||||
if len(totp_fields) == 0:
|
||||
return None
|
||||
return totp_fields
|
||||
|
||||
def is_trash(self):
|
||||
if "trashed" in self.raw:
|
||||
|
Loading…
x
Reference in New Issue
Block a user