LexxXell
@LexxXell
Программист и немного IT-журналист

Почему bcrypt ложно срабатывает?

Почему в этом коде ложно срабатывает bcrypt?
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');

const token1 = jwt.sign({
  sub: 1,
  email: 'test@test.test'
}, 'secret_1');
const token1Hashed = bcrypt.hashSync(token1, 5);

const token2 = jwt.sign({
    sub: 1,
    email: 'test@test.test'
  }, 'secret_2');
const token2Hashed = bcrypt.hashSync(token2, 5);

console.log(`Token1: ${token1}\n`);
console.log(`Token1 hashed: ${token1Hashed}\n`);
console.log(`Token2: ${token2}\n`);
console.log(`Token2 hashed: ${token2Hashed}\n`);

console.log(`Compare token1 vs token1Hashed: ${bcrypt.compareSync(token1, token1Hashed)}`);
console.log(`Compare token1 vs token2Hashed: ${bcrypt.compareSync(token1, token2Hashed)}`);
console.log(`Compare token2 vs token2Hashed: ${bcrypt.compareSync(token2, token2Hashed)}`);
console.log(`Compare token2 vs token1Hashed: ${bcrypt.compareSync(token2, token1Hashed)}`);

Токены получаются разными, их хеши тоже (сложность и степень различия секретов не влияют).

Вывод в консоль:
Token1: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImVtYWlsIjoidGVzdEB0ZXN0LnRlc3QiLCJpYXQiOjE2NjAwNTIwMDF9.UVjmLVq2PzGNoAcw8av4lwpp_3_TSCRzMokiP44tClw

Token1 hashed: $2a$05$IOawgfQ9oOMVNWNQ1pvm9O6/lEC3wLLkAx1YsqxuAxmb.Mmq387v.

Token2: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImVtYWlsIjoidGVzdEB0ZXN0LnRlc3QiLCJpYXQiOjE2NjAwNTIwMDF9.GZ0K7STNgC9tfwurA3LciMbU3wYqBLz9kBj5rnH-E4U

Token2 hashed: $2a$05$Vw2GumDtyQ9Q8kbQk1dXUuEICVXw7zj6ZHQMlNPU0LZpYR73y2YF2

Compare token1 vs token1Hashed: true
Compare token1 vs token2Hashed: true
Compare token2 vs token2Hashed: true
Compare token2 vs token1Hashed: true


Какие альтернативные необратимые методы шифрования можно использовать в данной ситуации?
  • Вопрос задан
  • 89 просмотров
Решения вопроса 1
LexxXell
@LexxXell Автор вопроса
Программист и немного IT-журналист
Как выяснили в комментариях, проблема в длине токенов, т.к. bcrypt может принять в себя только 72 байта.

Для конкретного случая - использование bcrypt для хеширования jwt токенов, можно использовать только сингатурную часть токена, в этом случае bcrypt работает.
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');

const payload = {
  sub: 1,
  email: 'testt@test.test'
}

const token1 = jwt.sign(payload, 'secret_1');
const token1Signature = token1.split('.').pop()
const token1SignatureHashed = bcrypt.hashSync(token1Signature, 5);

const token2 = jwt.sign(payload, 'secret_2');
const token2Signature = token2.split('.').pop()
const token2SignatureHashed = bcrypt.hashSync(token2Signature, 5);

console.log(`Token1 sig: ${token1Signature}\n`);
console.log(`Token1 sig hashed: ${token1SignatureHashed}\n`);
console.log(`Token2 sig: ${token2Signature}\n`);
console.log(`Token2 sig hashed: ${token2SignatureHashed}\n`);

console.log(`Compare token1Sig vs token1SigHashed: ${bcrypt.compareSync(token1Signature, token1SignatureHashed)}`);
console.log(`Compare token1Sig vs token2SigHashed: ${bcrypt.compareSync(token1Signature, token2SignatureHashed)}`);
console.log(`Compare token2Sig vs token2SigHashed: ${bcrypt.compareSync(token2Signature, token2SignatureHashed)}`);
console.log(`Compare token2Sig vs token1SigHashed: ${bcrypt.compareSync(token2Signature, token1SignatureHashed)}`);

Вывод в консоль:
Token1 sig: Z_cIJxKYkQsUWbu1hiRBiFjQOVGehfvcEH1SxJtBBvM

Token1 sig hashed: $2a$05$4yGh8r.YeNsrV3D9i/snMe6QMT1Pt7ZKBOlCZpSypcEdO4xZEnx7K

Token2 sig: XCVtQYxAGDcMMqCQBIitRyok61zJhzcr3c6PZppID2I

Token2 sig hashed: $2a$05$okXRKv85XY88Tg/RhBwuoOwNfGNtjVm8gFI8dzm79SXSvWMTKrULa

Compare token1Sig vs token1SigHashed: true
Compare token1Sig vs token2SigHashed: false
Compare token2Sig vs token2SigHashed: true
Compare token2Sig vs token1SigHashed: false
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@mayton2019
Bigdata Engineer
А какие типы аргументов принимает эта функция?
bcrypt.compareSync(...)
Там наверное строки надо толкать. Вообще распечатай на экране чему у тебя равно token1, token2Hashed
Ответ написан
SagePtr
@SagePtr
Еда - это святое
Следует для начала определиться, а зачем в данной ситуации вообще использовать bcrypt.
У bcrypt есть свои преимущества, недостатки и цели применения. Этот алгоритм хорош для паролей по той причине, что у него высокая вычислительная сложность и низкая скорость перебора, если злоумышленники утащат базу данных - то подобрать для паролей коллизии займёт очень много времени, если вообще им захочется этим заниматься.
Хэшировать этим алгоритмом токены не имеет никакого практического смысла, т.к. содержимое токена не представляет для злоумышленника никакой ценности - "публичная" часть собирается из данных, хранящихся в той же БД в открытом виде (id пользователя, емейл), а подпись - легко инвалидировать, сменив секрет после утечки БД.
Если же просто нужно в каком-то хэшированном виде хранить хэши токенов для сравнения между собой, то лучше воспользоваться любой "легковесной" хэш-функцией, например, sha1 (да или тупо в открытую хранить подписи токенов без самих токенов и уже их сравнивать). Много вычислительных раундов и соль в этой задаче абсолютно лишние по вышеуказанной причине. В большинстве случаев их и хранить не обязательно, достаточно проверять их подлинность после получения от клиента (хранить разве что в ситуации, когда есть механизм отзыва токенов и нужно проверять, не отозван ли он).
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы