== Password Vault== This app stores your passwords, protected by FingerPrint scan (if you have set it up) and a Master Password.\\ The Master Password is only stored in encrypted form, not in plaintext.\\ Similarly your site/app passwords are only stored in encrypted form.\\ The encryption keys are not in the code (the keys are your Master Password plus your DeviceID).\\ After providing your Master Password, you can add sites/apps and passwords.\\ Touching an entry in the list of sites and passwords shows a dialog\\ where you can copy the password to the clipboard (to pass into the app/site)\\ or edit the entry and save, or delete.\\ \\ Requires the Biometric plugin (or you could comment out that code)\\ app.LoadPlugin( "Biometric" ) var mpw // plaintext master password var empw // encrypted master password function OnStart() { salt = app.GetDeviceId() crpt = app.CreateCrypt() bio = app.CreateBiometric() lay = app.CreateLayout( "Linear", "Top,Left" ) txt = app.AddText(lay,"Password Vault") txt.SetTextSize(18) app.AddLayout( lay ) if(!bio.IsHardwareDetected()) getMasterPassword() else if(!bio.HasEnrolledFingerprints()) { app.ShowPopup("We would recommend setting up fingerprint security") getMasterPassword() } else { adlg = bio.CreateAuthDialog("Please scan your fingerprint", "Vault") adlg.SetOnSuccess(getMasterPassword) adlg.SetOnClose(function () {app.Quit("Exiting");}) adlg.Show() } // if } // fn function getMasterPassword () { //app.ClearData() // testing empw = app.LoadText("empw","") empw = empw.trim() // seems necessary if (empw == "") {option = "";} else {option = ",password";} te = app.AddTextEdit(lay,"",null,null,"singleline,nospell"+option) te.SetHint("Enter Master Password") te.Focus() if (empw == "") {te.SetOnEnter(newMasterPassword);} else {te.SetOnEnter(checkMasterPassword);} app.ShowKeyboard(te) } // fn function newMasterPassword() { mpw = this.GetText() if (mpw.length < 4) app.ShowPopup("Minimum length for Master Password is 4 characters") else {this.Hide() ; empw = crpt.Encrypt(mpw,mpw+salt) ; app.SaveText("empw",empw); opendb();} } // fn function checkMasterPassword() { gt = this.GetText() egt = crpt.Encrypt(gt,gt+salt) // encrypt user input egt = egt.trim() // seems necessary if (egt != empw) app.ShowPopup("Master Password doesn't match!") else {this.Hide(); mpw = gt ; opendb()} } // fn function opendb () { add = app.AddButton(lay,"[fa-plus-square-o] Add",null,null,"fontawesome") add.SetOnTouch(insert) lst = app.AddList(lay,"",0.8) lst.SetTextSize2(18,"px") lst.SetOnTouch(show) // db = app.OpenDatabase( "Vault" ) // does not work as APK db = app.OpenDatabase(app.GetPrivateFolder("Downloads")+"/Vault" ) db.ExecuteSql("CREATE TABLE IF NOT EXISTS passwords (site text primary key, epw text)") //db.ExecuteSql("DELETE FROM passwords",[],null,delError) // testing //epw = crpt.Encrypt("home",mpw+salt) // testing //db.ExecuteSql("INSERT INTO passwords (site, epw) VALUES (?,?)", ["home", epw], null, insError ) // testing db.ExecuteSql( "select * from passwords order by site;", [], display ) app.EnableBackKey(false) // close database if app closed } // fn function display(results) { var str = ""; for (var i = 0; i < results.rows.length; i++ ) { var item = results.rows.item(i) site = item.site epw = item.epw pw = crpt.Decrypt(epw,mpw+salt) if (str != "") str+="," str += site+":"+pw+":" } // for lst.SetList(str) } // fn function insert() { if (typeof dlgi == "undefined") { dlgi = app.CreateDialog("Add","old") layDlgi = app.CreateLayout("linear","left,vertical") layDlgi.SetSize(0.5,-1) dlgi.AddLayout(layDlgi) sa = app.AddTextEdit(layDlgi,"",null,null,"singleline,nospell") sa.SetHint("site or app") pwi = app.AddTextEdit(layDlgi,"",null,null,"singleline,nospell") pwi.SetHint("password") ent = app.AddButton(layDlgi,"[fa-save] Save",null,null,"fontawesome") ent.SetOnTouch(function () { i1 = sa.GetText() ; i2 = pwi.GetText() ; i2e = crpt.Encrypt(i2,mpw+salt) db.ExecuteSql("INSERT INTO passwords (site, epw) VALUES (?,?)", [i1,i2e], insSuccess, insError ) }) } else { sa.SetText("") pwi.SetText("") } dlgi.Show() app.ShowKeyboard(sa) } function show(title,body,icon,index) { gtitle = title if (typeof dlg == "undefined") { dlg = app.CreateDialog(title,"old") layDlg = app.CreateLayout("linear","left,vertical") layDlg.SetSize(0.5,-1) dlg.AddLayout(layDlg) row2 = app.AddLayout(layDlg,"linear","horizontal") cp2 = app.AddButton(row2,"[fa-copy] Copy",null,null,"fontawesome") cp2.SetOnTouch(function() {app.SetClipboardText(bdy.GetText());cp2.Focus();}) bdy = app.AddTextEdit(row2,body,null,null,"singleline,nospell") sve = app.AddButton(layDlg,"[fa-save] Save",null,null,"fontawesome") sve.SetOnTouch(function() { pw = bdy.GetText() ; epw = crpt.Encrypt(pw,mpw+salt); lst.SetItem(gtitle,gtitle,pw) db.ExecuteSql("UPDATE passwords SET epw = ? where site=? ;",[epw,gtitle],updSuccess,updError) dlg.Hide() }) del = app.AddButton(layDlg,"[fa-minus-square-o] Delete",null,null,"fontawesome") del.SetOnTouch(function() { lst.RemoveItem(gtitle) db.ExecuteSql("DELETE FROM passwords where site=?;",[gtitle],delSuccess,delError) dlg.Hide() }) } else { dlg.SetTitle(title) bdy.SetText(body) } dlg.Show() } function insSuccess(msg) { lst.AddItem(i1,i2) dlgi.Hide() } function insError(msg) { alert(msg) app.ShowPopup("insert failed, site/app must be unique") } function updSuccess(msg) { // alert(msg.rowsAffected) app.ShowPopup("updated") } function updError(msg) { alert(msg) app.ShowPopup("update failed") } function delSuccess(msg) { // alert(msg.rowsAffected) app.ShowPopup("deleted") } function delError(msg) { alert(msg) app.ShowPopup("delete failed") } function OnBack() { db.Close() app.Exit() }