« The Easy Bit
Jobs Not Done »

Escaping from Passman

For the last few years I have been keeping my passwords within a password manager called passman. Development of passman has been limited recently and for a while it was blocking me upgrading my nextcloud instance.

As a result I am now begining to worry that passman may not be a suitable password manager. If it takes them six months to release an update, how good are their security checks? I decided to export my passwords and try a different password manager however the password export function was broken. The issue is being tracked on github.

Towards the bottom of the issue, someone showed a way of hacking together some javascript to export all the passwords in the vault into a json file and another bit of code to convert them into a CSV.

I ran into issues with exporting the data from the console where some characters were double escaped. After an evening of playing with code, I combined the two parts into one block of code and included a download function. I also tweaked the CSV code to merge the list of tags into one string.

function download(filename, text) {
  var element = document.createElement('a');
  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
  element.setAttribute('download', filename);

  element.style.display = 'none';
  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);
}

mypasswords = []
PassmanExporter.getCredentialsWithFiles = function(credentials, FileService, EncryptService) {
            var t = {
                cred: credentials,
                FS: FileService,
                ES: EncryptService
            };
            return new C_Promise(function() {
                var _this = this.parent
                  , credentials = _this.cred;
                this.parent.total = 0,
                this.parent.finished = 0,
                this.parent.fileGUID_cred = [],
                this.parent.files = [],
                this.parent.step = function(file) {
                    this.parent.finished++,
                    this.call_progress({
                        total: this.parent.total,
                        finished: this.parent.finished
                    });
                    var dta = this.parent.fileGUID_cred[file.guid];
                    file.filename = this.parent.ES.decryptString(file.filename, this.parent.cred[dta.cred_pos].vault_key),
                    file.file_data = this.parent.ES.decryptString(file.file_data, this.parent.cred[dta.cred_pos].vault_key),
                    "files" === dta.on ? this.parent.cred[dta.cred_pos][dta.on][dta.at] = file : this.parent.cred[dta.cred_pos][dta.on][dta.at].value = file,
                    this.parent.total === this.parent.finished && this.call_then(this.parent.cred)
                }
                .bind(this);
                for (var i = 0; i < credentials.length; i++) {
                    var item = credentials[i];
                    for (c = 0; c < item.custom_fields.length; c++) {
                        var cf = item.custom_fields[c];
                        "file" === cf.field_type && (this.parent.total++,
                        this.parent.fileGUID_cred[cf.value.guid] = {
                            cred_pos: i,
                            on: "custom_fields",
                            at: c
                        },
                        this.parent.FS.getFile(cf.value).then(function(data) {
                            this.parent.step(data)
                        }
                        .bind(this)))
                    }
                    mypasswords.push(item)
                }
                b = ''

                mykeys = Object.keys(mypasswords[0])

                mykeys.forEach(function(data) { b = b + data + ',' })

                mypasswords.forEach(function(i) {
                b = b + "\n";
                mykeys.forEach(function(data) {
                    if (data == 'otp') {
                    b = b + i.otp.secret + ',';
                    } else if (data == 'tags'){
                    for (j = 0; j < i.tags.length; j++){
                        b = b + i.tags[j]['text'] + " ";    
                    }
                    b = b + ',';    
                    }else {
                    b = b + i[data] + ',';
                    }
                })
                })

                b = b + "\n";
                // This is to export as CSV
                download('passman.csv', b)

                // This is to export as json
                //download('passman.json', JSON.stringify(mypasswords) )
            }
            ,t)
        }

To use:

  • Open passman and unlock your vault
  • Navigate to the export vault page
  • Open up the web console (firefox Ctrl+Shift+K)
  • Copy and paste the block of code above
  • Run export as normal (it doesn't matter if you select CSV or JSON, you will get a CSV unless you uncomment the line that includes passman.json towards the bottom).

The CSV can then be imported into whatever password manager you want to try out next.

Go Top

Comments

To comment on this article, send me an email

No comments yet.