Добрый день. Нашли неплохую программу Passbolt CE, установили ее на свой сервер, все настроили, теперь хотим логиниться и получать пароли при помощи встроенного API, но возникает ряд проблем.
Сначала расшифровывает приватный ключ:
const fs = require('fs');
const openpgp = require('openpgp');
const axios = require('axios');
require('dotenv').config();
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const PASSPHRASE = process.env.PASSPHRASE;
const EMAIL = process.env.EMAIL;
const API_URL = process.env.API_URL;
async function loadPrivateKey() {
console.log('[2] Загружаем приватный ключ...');
const privateKeyArmored = fs.readFileSync(PRIVATE_KEY, 'utf8');
const privateKey = await openpgp.readPrivateKey({ armoredKey: privateKeyArmored });
if (privateKey.isDecrypted()) {
console.log('[INFO] Ключ уже расшифрован');
return privateKey;
}
const decryptedKey = await openpgp.decryptKey({ privateKey, passphrase: PASSPHRASE });
console.log('[INFO] Ключ расшифрован через passphrase');
return decryptedKey;
}
на этом этапе, если использовать приватный ключ от пользователя, который создавался при настройке приложения все ок, ключ расшифровывается. Если использовать серверный ключ server_private_key.asc, то пишет, что ключ уже расшифрован
следующий этап:
async function getChallenge() {
console.log('[1] Получаем challenge...');
const res = await axios.get(`${API_URL}/auth/verify.json?username=${encodeURIComponent(EMAIL)}`);
const challenge = res.data.body.fingerprint;
console.log('[CHALLENGE]', challenge);
return challenge;
}
Вот тут начинается веселье, он получает challenge, который равен fingerprint. Если я использую серверный приватный ключ, то отпечаток полученный от сервера passbolt (A505F33A1191319E787D0B2E5E92BA8A2C424B49, например) будет равен fingerprint этого серверного ключа и код пойдет дальше. Если я буду использовать приватный ключ пользователя, то на этом этапе я получу ошибку, что ❌ Подпись невозможна. Ожидался ключ с fingerprint A505F33A1191319E787D0B2E5E92BA8A2C424B49, но используем 999AAF9999E99999DC999A99CD99B990DE999999.
Если идти по первому пути с серверным приватным ключом, то этот участок проходит без ошибок:
async function signChallenge(challenge, decryptedKey) {
console.log('[3] Подписываем challenge...');
const message = await openpgp.createMessage({ text: challenge });
const detachedSignature = await openpgp.sign({
message,
signingKeys: decryptedKey,
detached: true,
format: 'binary'
});
const signatureBase64 = Buffer.from(detachedSignature).toString('base64'); // ← здесь исправили
return signatureBase64;
}
Ошибка у меня возникает, когда я пытаюсь авторизоваться:
async function loginJWT(fingerprint, signatureBase64) {
console.log('[4] Выполняем JWT авторизацию...');
try {
const response = await axios.post(`${API_URL}/auth/jwt/login.json`, {
gpg_auth: {
keyid: fingerprint,
signature: signatureBase64
}
});
console.log('[✅] Успешный ответ:', response.data);
} catch (err) {
if (err.response) {
console.error('[ОШИБКА ОТ СЕРВЕРА]', err.response.data);
} else {
console.error('[ОШИБКА]', err.message);
}
}
}
[4] Выполняем JWT авторизацию...
[ОШИБКА ОТ СЕРВЕРА] {
header: {
id: 'ff22369f-839f-4041-92ff-ff8af69ff1см',
status: 'error',
servertime: 1745821728,
action: '28c0972f-e6f2-5f44-f5fb-bf2f11799ee1',
message: 'Учетные данные недействительны.',
url: '/auth/jwt/login.json',
code: 400
},
body: ''
}
если же я не провожу сравнение на втором этапе с отпечатком от сервера и отпечатком пользователя, то возникает другая ошибка:
[2] Загружаем приватный ключ...
[INFO] Ключ расшифрован через passphrase
[1] Получаем challenge...
[CHALLENGE] A505F33A1191319E787D0B2E5E92BA8A2C424B49
[3] Подписываем challenge...
[4] Выполняем JWT авторизацию...
[ОШИБКА ОТ СЕРВЕРА] {
header: {
id: 'ff22369f-839f-4041-92ff-ff8af69ff1см',
status: 'error',
servertime: 1745827074,
action: '28c0972f-e6f2-5f44-f5fb-bf2f11799ee1',
message: 'Учетные данные недействительны.',
url: '/auth/jwt/login.json',
code: 400
},
body: ''
}
подскажите, пожалуйста, что идет не так.
Даже если фиксировать именно свой отпечаток, а не брать полученный от passbolt:
async function loginJWT(signatureBase64) {
console.log('[4] Выполняем JWT авторизацию...');
try {
const response = await axios.post(`${API_URL}/auth/jwt/login.json`, {
gpg_auth: {
keyid: FIXED_FINGERPRINT,
signature: signatureBase64
}
});
console.log('[✅ УСПЕХ] Ответ:', response.data);
} catch (err) {
if (err.response) {
console.error('[ОШИБКА ОТ СЕРВЕРА]', err.response.data);
} else {
console.error('[ОШИБКА]', err.message);
}
}
}
(async () => {
const privateKey = await loadPrivateKey();
const challenge = await getChallenge();
const signatureBase64 = await signChallenge(challenge, privateKey);
await loginJWT(signatureBase64);
})();
Я снова получаю ошибку, что message: 'Учетные данные недействительны.',