JavaScript Python PHP
import * as __biblioteca1 from "reflect-metadata";
import * as __biblioteca2 from "@peculiar/x509";
async function executar(values = { "domain": "localhost", "days": "30", "bits": "2048" }) {
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 pem(bytes, label) { return `-----BEGIN ${label}-----\n${toBase64(bytes).match(/.{1,64}/g).join('\n')}\n-----END ${label}-----\n`; }
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 required(values, key) {
if (!values[key])
throw new Error(`Preencha o campo ${key}.`);
return values[key];
}
function randomBytes(size) { return crypto.getRandomValues(new Uint8Array(size)); }
async function createCertificate(values) {
const domain = required(values, 'domain').trim().toLowerCase();
if (/^(?:\d+\.){3}\d+$/.test(domain) || domain.length > 253 || !/^(localhost|(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)$/.test(domain))
throw new Error('Use localhost ou um nome DNS válido, sem protocolo, porta ou caminho.');
const days = integer(values, 'days', 30, 1, 365);
const bits = Number(option(values, 'bits', ['2048', '3072', '4096'], '2048'));
await __biblioteca1;
const x509 = await __biblioteca2;
const algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256', modulusLength: bits, publicExponent: new Uint8Array([1, 0, 1]) };
const keys = await crypto.subtle.generateKey(algorithm, true, ['sign', 'verify']);
const serial = randomBytes(16);
serial[0] &= 127;
serial[15] |= 1;
const now = new Date();
const certificate = await x509.X509CertificateGenerator.createSelfSigned({
serialNumber: toHex(serial), name: `CN=${domain}`, notBefore: new Date(now.getTime() - 60000), notAfter: new Date(now.getTime() + days * 86400000), signingAlgorithm: algorithm, keys,
extensions: [new x509.BasicConstraintsExtension(false, undefined, true), new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature | x509.KeyUsageFlags.keyEncipherment, true), new x509.ExtendedKeyUsageExtension(['1.3.6.1.5.5.7.3.1']), new x509.SubjectAlternativeNameExtension([{ type: 'dns', value: domain }])],
}, crypto);
const cert = certificate.toString('pem');
const privateKey = pem(new Uint8Array(await crypto.subtle.exportKey('pkcs8', keys.privateKey)), 'PRIVATE KEY');
return { text: cert + '\n' + privateKey, message: `Certificado autoassinado para ${domain}, válido por ${days} dias.`, files: [{ name: 'certificate.crt', content: cert }, { name: 'private-key.pem', content: privateKey }] };
}
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.');
{
return createCertificate(values);
}
}
return await runSecurityTool("certificate", values);
}
from datetime import datetime, timedelta, timezone
from cryptography import x509
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
from cryptography.hazmat.primitives import hashes, serialization as s
from cryptography.hazmat.primitives.asymmetric import rsa
import re
def executar(values=None):
values = {'domain': 'localhost', 'days': '30', 'bits': '2048'} 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(domain='localhost', days=30, bits=2048):
if not domain or any((ch not in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-' for ch in domain)) or type(days) is not int or (not 1 <= days <= 365) or (type(bits) is not int) or (bits not in (2048, 3072, 4096)):
raise ValueError('Domínio, validade ou tamanho inválido')
results = []
key = rsa.generate_private_key(public_exponent=65537, key_size=bits)
name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, domain)])
now = datetime.now(timezone.utc)
cert = x509.CertificateBuilder().subject_name(name).issuer_name(name).public_key(key.public_key()).serial_number(x509.random_serial_number()).not_valid_before(now).not_valid_after(now + timedelta(days=days)).add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=True).add_extension(x509.KeyUsage(digital_signature=True, content_commitment=False, key_encipherment=True, data_encipherment=False, key_agreement=False, key_cert_sign=False, crl_sign=False, encipher_only=False, decipher_only=False), critical=True).add_extension(x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH]), critical=False).add_extension(x509.SubjectAlternativeName([x509.DNSName(domain)]), critical=False).sign(key, hashes.SHA256())
results.append(cert.public_bytes(s.Encoding.PEM).decode())
results.append(key.private_bytes(s.Encoding.PEM, s.PrivateFormat.PKCS8, s.NoEncryption()).decode())
return results[0] if len(results) == 1 else results
if re.fullmatch(r'(?:[0-9]+\.){3}[0-9]+',values.get('domain','')) or not re.fullmatch(r'localhost|(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?',values.get('domain','').strip().lower()) or len(values.get('domain',''))>253: raise ValueError('Domínio DNS inválido')
result = process(domain=values.get('domain', ''), days=integer('days'), bits=integer('bits'))
return {'text':result[0]+'\n'+result[1], 'message':f"Certificado autoassinado para {values['domain']}, válido por {values['days']} dias.", 'files':[{'name':'certificate.crt','content':result[0]},{'name':'private-key.pem','content':result[1]}]}
<?php
function executar($values = ['domain'=>'localhost','days'=>'30','bits'=>'2048']) {
$domain=strtolower(trim($values['domain'] ?? ''));
if (strlen($domain)>253 || preg_match('/^(?:[0-9]+\.){3}[0-9]+$/D',$domain) || !preg_match('/^(localhost|(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)$/D',$domain)) throw new InvalidArgumentException('Domínio DNS inválido');
$days=$values['days'] ?? '30'; $bits=$values['bits'] ?? '2048';
if (!preg_match('/^[0-9]+$/D',$days) || (int)$days<1 || (int)$days>365 || !in_array($bits,['2048','3072','4096'],true)) throw new InvalidArgumentException('Validade ou tamanho inválido');
// The configuration is visible and generated here; no project file is loaded.
$config="[req]\ndistinguished_name=dn\nprompt=no\nreq_extensions=server\nx509_extensions=server\n[dn]\nCN=".$domain."\n[server]\nbasicConstraints=critical,CA:FALSE\nkeyUsage=critical,digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth\nsubjectAltName=DNS:".$domain."\n";
$temporary=tempnam(sys_get_temp_dir(),'json-tools-cert-');
if ($temporary===false) throw new RuntimeException('Não foi possível criar configuração temporária');
try {
if (file_put_contents($temporary,$config)===false) throw new RuntimeException('Falha ao gravar configuração');
$options=['config'=>$temporary,'digest_alg'=>'sha256','private_key_type'=>OPENSSL_KEYTYPE_RSA,'private_key_bits'=>(int)$bits,'x509_extensions'=>'server','req_extensions'=>'server'];
$key=openssl_pkey_new($options);
$csr=$key ? openssl_csr_new(['commonName'=>$domain],$key,$options) : false;
$certificate=$csr ? openssl_csr_sign($csr,null,$key,(int)$days,$options,random_int(1,PHP_INT_MAX)) : false;
if (!$certificate || !openssl_x509_export($certificate,$pem) || !openssl_pkey_export($key,$private,null,$options)) throw new RuntimeException('Falha técnica do OpenSSL');
$result=['text'=>$pem."\n".$private,'message'=>'Certificado autoassinado para '.$domain.', válido por '.$days.' dias.','files'=>[['name'=>'certificate.crt','content'=>$pem],['name'=>'private-key.pem','content'=>$private]]];
} finally { unlink($temporary); }
return $result;
}