Created
January 20, 2023 20:01
-
-
Save simojo/345e3f9537ae00081bcc2ce4a5b37ed4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// migrating from password-store (aka pass) to bitwarden. | |
// by Simon Jones (2023) | |
// | |
// note: I do not use bitwarden, this is for you to use. | |
// this script assumes you have: | |
// 1. decrypted all of your password-store gpg encrypted files | |
// and put them in a folder named 'passDecryptedFiles'. | |
// 2. a directory structure as follows: | |
// ./ | |
// ├ migratePassToBitwarden.js | |
// └ passDecryptedFiles/ | |
// ├ file1.gpg.txt | |
// ├ file2.gpg.txt | |
// ├ file3.gpg.txt | |
// ├ file4.gpg.txt | |
// ├ ... | |
// └ fileN.gpg.txt | |
// | |
// good luck. | |
const fs = require("fs"); | |
const path = require("path"); | |
const directoryName = "passDecryptedFiles"; | |
const fullPath = path.join(__dirname, directoryName) | |
fs.readdir(fullPath, (error1, files) => { | |
if (error1) throw error1; | |
let passwordObjs = files.map(f => { | |
let passwordObj; | |
passwordObj = handleFileText( | |
f, | |
fs.readFileSync(path.join(__dirname, directoryName, f), {encoding: "utf8", flag: "r"}) | |
); | |
return passwordObj; | |
}); | |
fs.writeFile("OUTPUT.txt", JSON.stringify({ | |
"encrypted": false, | |
"folders": [], | |
"items": passwordObjs | |
}), (e) => { if (e) throw e; }); | |
}); | |
function createUUID() { | |
// http://www.ietf.org/rfc/rfc4122.txt | |
var s = []; | |
var hexDigits = "0123456789abcdef"; | |
for (var i = 0; i < 36; i++) { | |
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); | |
} | |
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010 | |
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01 | |
s[8] = s[13] = s[18] = s[23] = "-"; | |
var uuid = s.join(""); | |
return uuid; | |
} | |
function handleFileText(fname, text) { | |
let splits = text.split("\n"); | |
let p = splits[0]; | |
if (p === "") { | |
let res= { | |
"id": createUUID(), | |
"organizationId": null, | |
"folderId": null, | |
"type": 1, | |
"reprompt": 0, | |
"name": fname.replace(".gpg.txt", ""), | |
"notes": text, | |
"favorite": false, | |
"fields": [], | |
"login": { | |
"uris": [], | |
"username": "", | |
"password": "", | |
"totp": null | |
}, | |
"collectionIds": null | |
}; | |
return res; | |
} | |
let keyvalues = splits.slice(1) | |
.filter(x => /^.*?:\s.+$/.test(x) === true) | |
.map(x => ({ | |
key: x.split(":")[0].trim(), | |
value: x.split(":").slice(1).join(":").trim() | |
})); | |
let username = keyvalues.filter(x => x.key === "username")[0]?.value; | |
if (username != null) keyvalues = keyvalues.filter(x => x.key !== "username"); | |
let notes = keyvalues.filter(x => x.key === "notes")[0]?.value; | |
if (notes != null) keyvalues = keyvalues.filter(x => x.key !== "notes"); | |
let url = keyvalues.filter(x => x.key === "url")[0]?.value; | |
if (url != null) keyvalues = keyvalues.filter(x => x.key !== "url"); | |
let res= { | |
"id": createUUID(), | |
"organizationId": null, | |
"folderId": null, | |
"type": 1, | |
"reprompt": 0, | |
"name": fname.replace(".gpg.txt", ""), | |
"notes": notes, | |
"favorite": false, | |
"fields": keyvalues.map(x => ({ | |
"name": x.key, | |
"value": x.value, | |
"type": 0, | |
"linkedId": null | |
})), | |
"login": { | |
"uris": (url == null ? [] : [ | |
{ | |
"match": null, | |
"uri": url | |
} | |
]), | |
"username": username, | |
"password": p, | |
"totp": null | |
}, | |
"collectionIds": null | |
}; | |
return res; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment