Pular para o conteúdo

Catálogo de demonstração. Produtos, criadores, preços e avaliações são fictícios. Recursos gratuitos podem ser adquiridos de verdade; itens pagos não são cobrados nem simulados. Ver o que já funciona

Modelo de segurança

O que o serviço garante, o que ele não garante, e as decisões por trás de cada escolha.

A premissa

O plugin roda na máquina do cliente. Ele não pode guardar segredo nenhum: um .jar é um zip, e quem controla a máquina lê tudo que há dentro.

Todo o desenho parte disso. Nada no sistema depende de o plugin esconder alguma coisa.

Por que assimétrico

HMAC exigiria que o verificador tivesse o mesmo segredo do emissor — ou seja, um segredo dentro de cada .jar distribuído. Com assinatura assimétrica, o plugin carrega apenas a chave pública.

Descompilar o plugin, extrair a chave e estudá-la não produz nada: forjar uma autorização exigiria a chave privada, que nunca sai da plataforma.

ComponenteOnde vivePara que serve
Chave privada Ed25519Banco da plataforma, cifrada com AES-256-GCMAssinar autorizações. Nunca sai.
Chave públicaPublicada em /.well-known/keysVerificar. Qualquer um pode baixar.
Chave de licençaconfig.yml do clienteAutenticar o cliente. ~98 bits de entropia.
Product IDDentro do .jar, à vistaIdentificar o produto. Público e inofensivo.
Chave de APIServidor do vendedor, em variável de ambienteGerenciar plugins e licenças. NUNCA em um .jar.

IP e porta: pista, não prova

O endereço chega declarado pelo cliente

O servidor que está sendo verificado é quem informa o próprio endereço. Não há nada de criptográfico nisso. Um atacante que já tem a chave consegue declarar qualquer IP.

Então para que serve o vínculo por IP?

  • Contra compartilhamento casual. Quem passa a chave para um amigo não costuma editar o plugin para mentir o IP; ele só instala e falha.
  • Como trilha. Cada recusa fica registrada com o que foi declarado e com o hash do IP observado pela borda. Divergência entre os dois é exatamente o sinal que você procura no painel.
  • Como limite operacional. Combinado com o teto de instalações e com a chave, torna a redistribuição cara e visível.

Onde o vínculo por IP quebra sozinho

CenárioO que acontece
IP dinâmicoO provedor troca o IP e a licença para de valer no meio da noite. Sem aviso, para um cliente que não fez nada errado.
NAT / CGNATVários clientes diferentes aparecem com o mesmo IP. O vínculo deixa de distinguir qualquer coisa.
Hospedagem compartilhadaO painel move o servidor de máquina entre reinícios; o IP muda sozinho.
Proxy / VelocityO IP que o plugin enxerga é o do proxy, não o do backend — e vários backends compartilham o mesmo.

Por isso o padrão é vínculo por instalação

O identificador de instalação é gerado e persistido pelo SDK no disco do servidor: sobrevive à troca de IP e distingue máquinas atrás do mesmo NAT. Quem escolher IP ou IP_PORT vê esse aviso na própria tela de configuração da política.

A recusa não ensina

Chave inexistente, chave de outro produto e segredo errado devolvem a mesma resposta: license_not_valid, com o mesmo status e o mesmo corpo.

Distingui-los transformaria a rota em um oráculo: bastaria testar chaves até alguma responder “existe, mas é de outro produto”.

Os códigos de diagnóstico — license_expired, installation_limit_reached, binding_mismatch — só aparecem depois que a chave foi provada. Nesse ponto não há o que proteger: a pessoa tem a credencial, e esconder o motivo só faria o administrador legítimo abrir um chamado.

Contra reapresentação

Três mecanismos, todos obrigatórios:

  • requestId único por resposta. O SDK confere que é o mesmo da solicitação que ele acabou de enviar.
  • nonce ecoado. Valor aleatório gerado pelo cliente a cada chamada, devolvido dentro do documento assinado. Amarra a resposta à solicitação.
  • Prazo dentro da assinatura. expiresAt e graceUntil estão no payload assinado — não há como esticá-los sem invalidar a assinatura.

Rotação de chave de assinatura

Existe, a qualquer momento, no máximo uma chave ACTIVE. Rotacionar gera um par novo e move o anterior para RETIRED.

Uma chave aposentada não assina mais, mas continua publicada. É isso que permite rotacionar sem derrubar servidor de cliente: as autorizações já entregues seguem verificáveis até expirarem sozinhas.

REVOKED é o caso de comprometimento: sai da publicação na hora, e tudo que ela assinou deixa de ser verificável. É uma decisão operacional cara — por isso é uma ação separada de “aposentar”.

Revogação de licença

Revogar derruba as sessões ativas junto. Sem isso, a revogação só valeria depois que o documento assinado expirasse sozinho — até uma hora de acesso indevido.

O SDK também apaga a autorização guardada ao receber uma recusa definitiva, para que o modo offline não mantenha uma licença revogada viva até o fim do grace period.

SSRF em webhooks

Um webhook é, por definição, “a aplicação faz uma requisição para uma URL que um usuário escolheu”. Sem controle, isso é SSRF pronto.

  • Apenas HTTPS, apenas porta 443.
  • Resolução de DNS antes de conectar, com recusa de endereço privado, loopback, link-local, multicast e dos ranges de metadados de nuvem — incluindo 169.254.169.254 e os equivalentes IPv6.
  • A validação roda no cadastro e de novo a cada entrega: um domínio público pode passar a resolver para 127.0.0.1 depois de aprovado.
  • Sem seguir redirecionamento. Um 302 para endereço interno anularia tudo acima.
  • Timeout curto e corpo de resposta truncado.

Como a chave de licença é guardada

Quatro derivações, com propósitos separados:

ColunaO que éPara quê
keyHashHMAC-SHA256Autenticar, em tempo constante.
keyLookupHMAC com outra chave derivadaAchar a linha em O(1). Achar NÃO é autenticar: as duas derivações usam info diferente no HKDF.
keyEncryptedAES-256-GCM, reversívelPermitir que o TITULAR veja a própria chave no painel.
keyHintÚltimos 4 caracteresExibir em listagem.

Por que a chave é recuperável — e o que isso custa

A emissão automática acontece em segundo plano, quando o pedido é confirmado: ninguém está olhando, e não há tela para mostrar a chave. Se o banco guardasse só o hash, o comprador jamais conseguiria a própria chave — a compra entregaria um plugin inutilizável.

O custo, dito com todas as letras: um dump do banco deixa de ser inofensivo. O que ele não custa: a cifra usa chave derivada do segredo da aplicação, que não está no banco — é preciso ter os dois. A decifra acontece em um único lugar, sob guarda de propriedade, com limite de taxa e registro de auditoria.

Limites honestos

O que nenhum sistema de licença resolve

  • Quem controla o servidor pode remover a chamada de verificação do bytecode. O SDK não tenta se esconder disso, e ofuscação não mudaria o resultado — só tornaria o código impossível de auditar para quem é honesto.
  • Nada impede alguém de comprar, baixar o .jar e republicá-lo em um fórum.
  • Um cliente determinado a não pagar vai encontrar uma forma. O objetivo é que isso custe mais trabalho do que pagar.

O que o Lodestone Licensing entrega de verdade: compartilhamento casual deixa de funcionar, há teto de instalações simultâneas, toda tentativa fica registrada com o motivo, e dá para revogar na hora — valendo na próxima verificação, não no próximo reinício.

Prometer mais que isso seria vender DRM, que não existe. O Playground inclui um cenário de resposta adulterada, que demonstra exatamente onde a proteção começa e onde ela termina.