import { getPassword as getFromKeychain, setPassword, deletePassword as deleteFromKeychain } from 'keytar';
const env = process.env;
const { PT_ONLY } = env;const prefix = PT_ONLY ? ‘org.openvpn.privatetunnel’ : ‘org.openvpn.client.’;
const crypto = require(‘crypto’);
const ALGORITHM_NAME = ‘aes-128-gcm’;
const ALGORITHM_NONCE_SIZE = 12;
const ALGORITHM_TAG_SIZE = 16;
const ALGORITHM_KEY_SIZE = 16;
const PBKDF2_NAME = ‘sha1’;
const PBKDF2_SALT_SIZE = 16;
const PBKDF2_ITERATIONS = 32767;function encryptString(plaintext, password) {
try {
const salt = crypto.randomBytes(PBKDF2_SALT_SIZE);
const key = crypto.pbkdf2Sync(
Buffer.from(password, ‘utf8’),
salt,
PBKDF2_ITERATIONS,
ALGORITHM_KEY_SIZE,
PBKDF2_NAME
);const ciphertextAndNonceAndSalt = Buffer.concat([salt, encrypt(Buffer.from(plaintext, 'utf8'), key)]); return ciphertextAndNonceAndSalt.toString('base64'); } catch (e) { console.warn(e); }
}
function decryptString(base64CiphertextAndNonceAndSalt, password) {
try {
const ciphertextAndNonceAndSalt = Buffer.from(base64CiphertextAndNonceAndSalt, ‘base64’);
const salt = ciphertextAndNonceAndSalt.slice(0, PBKDF2_SALT_SIZE);
const ciphertextAndNonce = ciphertextAndNonceAndSalt.slice(PBKDF2_SALT_SIZE);const key = crypto.pbkdf2Sync( Buffer.from(password, 'utf8'), salt, PBKDF2_ITERATIONS, ALGORITHM_KEY_SIZE, PBKDF2_NAME ); return decrypt(ciphertextAndNonce, key).toString('utf8'); } catch (e) { console.warn(e); }
}
function encrypt(plaintext, key) {
const nonce = crypto.randomBytes(ALGORITHM_NONCE_SIZE);
const cipher = crypto.createCipheriv(ALGORITHM_NAME, key, nonce);
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
return Buffer.concat([nonce, ciphertext, cipher.getAuthTag()]);
}function decrypt(ciphertextAndNonce, key) {
const nonce = ciphertextAndNonce.slice(0, ALGORITHM_NONCE_SIZE);
const ciphertext = ciphertextAndNonce.slice(
ALGORITHM_NONCE_SIZE,
ciphertextAndNonce.length - ALGORITHM_TAG_SIZE
);
const tag = ciphertextAndNonce.slice(ciphertext.length + ALGORITHM_NONCE_SIZE);
const cipher = crypto.createDecipheriv(ALGORITHM_NAME, key, nonce);
cipher.setAuthTag(tag);
const res = Buffer.concat([cipher.update(ciphertext), cipher.final()]);
return res;
}
// const es = encryptString(‘test123’, ‘profname’);
// console.log(es);
// console.log(decryptString(es, ‘profname’));export async function savePassword(profile, password) {
return setPassword(prefix, profile, encryptString(password, profile));
}export async function getPassword(profile) {
return getFromKeychain(prefix, profile).then((s) => decryptString(s, profile));
}export function deletePassword(profile) {
return deleteFromKeychain(prefix, profile);
}export async function savePrivateKeyPassword(profile, password) {
return setPassword(prefix,${profile}.pkp
, encryptString(password, profile));
}export function getPrivateKeyPassword(profile) {
return getFromKeychain(prefix,${profile}.pkp
).then((s) => decryptString(s, profile));
}export function deletePrivateKeyPassword(profile) {
return deleteFromKeychain(prefix,${profile}.pkp
);
}export async function changePassProfile(oldName, newName) {
const pass = await getPassword(oldName);
if (!pass) {
return;
}
await savePassword(newName, pass);
await deletePassword(oldName);
}
export async function changePkpProfile(oldName, newName) {
const pass = await getPrivateKeyPassword(oldName);
if (!pass) {
return;
}
await savePrivateKeyPassword(newName, pass);
await deletePrivateKeyPassword(oldName);
}