async function executar(values = { "bytes": "32", "format": "base64url" }) {
function toHex(bytes) { return [...bytes].map(byte => byte.toString(16).padStart(2, '0')).join(''); }
function toBase64(bytes) {
let binary = '';
for (let i = 0; i < bytes.length; i += 8192)
binary += String.fromCharCode(...bytes.subarray(i, i + 8192));
return btoa(binary);
}
function toBase64Url(bytes) { return toBase64(bytes).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); }
function integer(values, key, fallback, min, max) {
const raw = values[key] ?? String(fallback);
const value = Number(raw);
if (!/^\d+$/.test(raw) || !Number.isSafeInteger(value) || value < min || value > max)
throw new Error(`${key}: informe um inteiro entre ${min} e ${max}.`);
return value;
}
function option(values, key, options, fallback) {
const value = values[key] ?? fallback;
if (!options.includes(value))
throw new Error(`Opção inválida: ${key}.`);
return value;
}
function randomBytes(size) { return crypto.getRandomValues(new Uint8Array(size)); }
function encoded(bytes, format) { return format === 'hex' ? toHex(bytes) : format === 'base64' ? toBase64(bytes) : toBase64Url(bytes); }
async function runSecurityTool(kind, values) {
if (!crypto.subtle)
throw new Error('Esta ferramenta requer Web Crypto em HTTPS ou localhost.');
if (Object.values(values).some(value => value.length > 1000000))
throw new Error('Limite de entrada: 1 milhão de caracteres por campo.');
{
{
const size = integer(values, 'bytes', kind === 'salt' ? 16 : 32, 16, 128);
const token = encoded(randomBytes(size), option(values, 'format', ['hex', 'base64', 'base64url'], 'base64url'));
if (kind === 'api-key') {
const prefix = values.prefix ?? 'bennu_';
if (!/^[A-Za-z0-9_-]{0,24}$/.test(prefix))
throw new Error('O prefixo deve ter até 24 letras, números, hífens ou sublinhados.');
return { text: prefix + token };
}
return { text: token };
}
}
}
return await runSecurityTool("csrf", values);
}
import secrets
import base64
import re
def executar(values=None):
values = {'bytes': '32', 'format': 'base64url'} if values is None else values
if not isinstance(values, dict) or any(not isinstance(v,str) or len(v.encode('utf-16-le',errors='surrogatepass')) // 2 > 1000000 for v in values.values()): raise ValueError('Informe campos textuais de até 1 milhão de caracteres')
def integer(key):
raw = values.get(key,'')
if not re.fullmatch(r'[0-9]+',raw): raise ValueError('Informe inteiro válido: ' + key)
return int(raw)
def process(bytes=32, format='base64url'):
if type(bytes) is not int or not 16 <= bytes <= 128:
raise ValueError('Tamanho: 16 a 128 bytes')
def encode(raw):
if format == 'hex':
return raw.hex()
if format == 'base64':
return base64.b64encode(raw).decode('ascii')
if format == 'base64url':
return base64.urlsafe_b64encode(raw).rstrip(b'=').decode('ascii')
raise ValueError('Formato inválido')
return encode(secrets.token_bytes(bytes))
result = process(bytes=integer('bytes'), format=values.get('format', ''))
return {'text':result}
<?php
function executar($values = ['bytes'=>'32','format'=>'base64url']) {
foreach ($values as $value) if (!is_string($value) || strlen($value)>1000000) throw new InvalidArgumentException("Informe campos textuais de até 1 milhão de bytes");
$integer = function ($key) use ($values) { $raw = $values[$key] ?? ""; if (!preg_match("/^[0-9]+$/D",$raw)) throw new InvalidArgumentException("Inteiro inválido: " . $key); return (int)$raw; };
$process = function ($bytes = 32, $format = 'base64url') {
if (!is_int($bytes) || $bytes < 16 || $bytes > 128) throw new InvalidArgumentException('Tamanho: 16 a 128 bytes');
$encode = function ($raw) use ($format) {
return match ($format) {
'hex' => bin2hex($raw),
'base64' => base64_encode($raw),
'base64url' => rtrim(strtr(base64_encode($raw), '+/', '-_'), '='),
default => throw new InvalidArgumentException('Formato inválido'),
};
};
return $encode(random_bytes($bytes));
};
$result = $process($integer('bytes'), $values['format'] ?? '');
return ['text'=>$result];
}