Как создать одноразовый номер в node.js?
Мне нужно сгенерировать одноразовый номер (число генерируется только один раз), чтобы удалить правило CSP 'unsafe-inline'
и все доверенные URL-адреса для сценариев, улучшающие оценку CSP. Таким образом мне нужно иметь в HTML
<script nonce="{{{nonce}}}" src="http://example.com/file.js">
Я знаю, что одноразовый номер должен быть уникальным с методом вычисления, который почти невозможно предсказать, он должен иметь не менее 128 бит (следовательно, 16 байтов) и быть закодирован в base64. Поэтому это правильно для node.js
?
const crypto = require('crypto');
let nonce = crypto.randomBytes(16).toString('base64');
4 ответа
Просто чтобы подтвердить, что это действительно работает в NodeJS для одноразовых номеров CSP
const crypto = require('crypto');
let nonce = crypto.randomBytes(16).toString('base64');
я предлагаю использовать
uuid
для этого: https://www.npmjs.com/package/uuid
Каждый uuid имеет размер ровно 16 байт (128 бит), как и хотелось бы, и у вас больше вероятность того, что ваш компьютер будет поражен метеором, чем столкновение uuid.
Вы можете использовать встроенныйдля генерации UUIDv4 (версия 4).
Это строка длиной 36 символов (288 бит), которая кодирует 128-битный UUID.
Из этих 128 бит только 122 бита являются случайными, 4 бита используются для кодирования версии UUID (всегда версия 4 дляrandomUUID()
), а 2 других бита фиксированы, поэтому всего вы теряете 6 бит случайности.
const crypto = require('crypto')
crypto.randomUUID()
'5a388e8e-09eb-4778-a242-ea663f3c7e5e'
Первый4
в-4478-
указывает, что это UUID версии 4, то есть 4 бита, которые не являются случайными.
Первые два бита-a242-
фиксируются на10
по спецификации RFC, так что они тоже не случайны.
Всего у вас есть 122-битная случайность, если вы используете UUIDv4 в качестве одноразового номера.
Вы можете сгенерировать 128-битный абсолютно случайный одноразовый номер с помощьюcrypto.randomBytes(16)
и закодируйте его в base64url (22 символа), base64 (24 символа) или hex (32 символа), все они короче, чем UUIDv4, который составляет 36 символов.
UUIDv4 длиннее (менее компактен) и содержит меньше случайных битов, но его легче читать при устранении неполадок, и его легко распознать как случайное значение.
crypto.randomUUID() # 36 characters
'5a388e8e-09eb-4778-a242-ea663f3c7e5e'
var nonce128bitvalue = crypto.randomBytes(16) # 16 * 8 = 128 bits
nonce128bitvalue.toString('base64url') # 22 characters long
'q-UBP7J_AqOn1BWTBq1Tfw'
nonce128bitvalue.toString('base64') # 24 characters long
'q+UBP7J/AqOn1BWTBq1Tfw=='
nonce128bitvalue.toString('hex') # 36 characters long
'abe5013fb27f02a3a7d4159306ad537f'
Как указано вcrypto.randomUUID()
документация:
Генерирует случайный UUID RFC 4122 версии 4.UUID генерируется с помощью криптографического генератора псевдослучайных чисел.
Лучше:
<script nonce="{{nonce}}" .. if you use HBS
not <script nonce="{{{nonce}}}"
in HBS convention: {{{body}}} vs {{title}} ,{{nonce}} or {{any_rendered_var}}
И в app.js среды разработки:
const crypto=require('crypto');
var nonce=crypto.randomBytes(16).toString("hex");
app.get('/', function(req, res) {res.render('index',{title:'Welcome',nonce:nonce});});
Это не защитит вас от кросс-скриптинга, потому что вы только что отрендерили случайное значение в nonce, и ваше приложение не знает ни о каком кросс-скриптинге, ни о том, почему вы отрендерили случайное значение nonce или nnc или любое другое имя переменной.
Но вы должны использовать пакет npm для шлема в продакшене!
так в server.js:
const crypto=require('crypto');
var nonce=crypto.randomBytes(16).toString("hex");
app.get('/', function(req, res) {res.render('index',{title:'Welcome',nonce:nonce});});
//add
const helmet = require('helmet');
Шлем заблокирует одноразовый номер, и в браузере вы увидите: <script nonce="" .. потому что для шлема CSP требуется:<script nonce="random_value_client===csp_helmet_random_value_server" ..
чтобы действительно предотвратить кросс-скриптинг