[Ajuda] Criando Ativação para comercializar software

Olá a todos, sou novo aqui no fórum, mas já tirei diversas dúvidas em outros posts aqui.
Minha dúvida é a seguinte. Eu conclui “ainda faltam alguns detalhes rsrs” um software para o controle de estoque de uma farmácia, pois tem um sistema aqui em minha cidade que várias farmácias usam, porém ele faz o controle apenas da parte financeira e de emissão de notas, e não tem uma parte destinada somente ao controle de estoque. Fiz uma busca pela internet e alguns foruns mas não encontrei nada que tira-se minha dúvida.
Como eu faço o software precisar de um “serial/codigo” para ser ativado? a principio não quero inserir esse código quando eu entrar no programa, e sim colocar o código no código fonte antes de criar o .jar
ou seja, o usuário nunca vai poder ativar, mesmo tendo o código, eu vou colocar o código no código fonte e então substituir o anterior.
Sendo que o mesmo processo devera ser feito em determinados dias, a final o software vai ser pago por mês. exemplo “a cada 30 dias terei que gerar um novo .exe” com um novo código

Acho que não fui muito claro, rsrs mas qualquer coisa vou explicando melhor

PS: digo isso pq já vi em uma empresa, no cara abria um aplicativo que era só dele, e clicava em “capturar NIR” então ele pegava aquele código e colocava dentro do código antes de criar o executável.

Estou com o mesmo problema rsrs algumas soluções que vi seria:
1 - Colocar no programa um serial que atualizasse o banco do pc local com uma data fixa, tipo 21/03/2016, dai ele pagou ganha mais 30 dias, dai atualizo la no banco dele com uma nova data, caso ele n pague o programa ve a data e se tiver passado ele n funciona, o problema seria o user mudar a data do pc rsrs
Outro ponto que vi e que acho que irei usar, sera:
2 - O programa que fiz ira realizar backup automatico do banco de dados uma vez por semana para uma hospedagem minha, onde armazenarei os dados caso haja algum problema, estou pensando em ter uma tabela com um simples true e false, toda vez q o programa va fazer o backup, ou ate mesmo, todo dia ele averigua na tabela se pode ligar, caso n possa n funciona, o problema é que o usuario teria que ter internet para usar o sistema dai.

Estou pesquisando sobre serial tb, mais tarde posto oq eu conseguir :smiley:

Estou com o mesmo problema rsrs algumas soluções que vi seria:
1 - Colocar no programa um serial que atualizasse o banco do pc local com uma data fixa, tipo 21/03/2016, dai ele pagou ganha mais 30 dias, dai atualizo la no banco dele com uma nova data, caso ele n pague o programa ve a data e se tiver passado ele n funciona, o problema seria o user mudar a data do pc rsrs
Outro ponto que vi e que acho que irei usar, sera:
2 - O programa que fiz ira realizar backup automatico do banco de dados uma vez por semana para uma hospedagem minha, onde armazenarei os dados caso haja algum problema, estou pensando em ter uma tabela com um simples true e false, toda vez q o programa va fazer o backup, ou ate mesmo, todo dia ele averigua na tabela se pode ligar, caso n possa n funciona, o problema é que o usuario teria que ter internet para usar o sistema dai.
Estou pesquisando sobre serial tb, mais tarde posto oq eu conseguir :smiley:

Amigo sua ideia foi muito bem vinda, mas pra ser sincero quero uma coisa mais profissional. hashhashsa
Creio que também da pra fazer com uma variável no código, mas como já disse, quero uma coisa mais prossional.
Caso não consiga vou seguir sua dica!
;D

Pois é kkkk tb queria mais profissa mas acho que vou fazer o seguinte no meu:
1 - Uma tabela local com uma data de validade, e o programa vai sempre que ligado verificar se esta dentro do prazo;
2

  • Caso o usuario mude a data do pc, irei fazer um Script basico para
    que uma vez conectado na net ele verifique em minha hospedagem em uma
    tabela la se o produto esta ok, se n estiver atualiza o banco do
    programa para travar kkkk

Ao menos o cara vai ter q ficar trocando a data e n vai poder
utilizar a net no pc mais kkkkk fora que fiz um esquema para o programa
toda sexta feira realizar um backup automatico exportando o banco de
dados para a nuvem, ai o user perde esse beneficio tb xD estou fzd
contrato ai nele vou colocar que quando o termino da licença acabar e o
usuario nao quiser mais renovar, um responsavel ira la retirar o
programa da maquina do cliente Ainda estou vendo de utilizar um esquema de pegar o endereço MAC para restringir aa maquinas que vão utilizar o sistema…

Só uma pergunta cliente ai não tem internet? oloco…
porque eu faço asssim…serial da maquina…cpf e senha validando em mysql remoto…assim controla a quantidade não deixa quem não deve usar…só que teria que ter internet claro

Pois é Lfbdsan tem uma slojas que estou disponibilizando o programa que nao tem internet rsrs e nao queria forçar o usuario a ter visto que alem de ter a mensalidade do software teria que ter uma internet tb, caso tivesse eu faria em web acho, assim ele acessaria o sistema em qualquer lugar :smiley: isso que vc falou que é uma das minhas opçoes ate kkk Mas um exemplo o avast, ele quando registra vc pode ficar sem internet e mudar a data que n importa deu 365 o miseravi pede pra ativar novamente, digo isso pq tenho um sitio e la tem duas maquina antigas uma com linux e uma com windows, na com windows coloquei ele, e ativei auqi em casa antes de levar e la expirou mesmo tentando burlar kkk

Eu trabalhava com um erp que a licença era um arquivo cripto…mas da mesma forma o cliente tinha que baixar a licença ou você teria que atualizar…mas acho que e o mais seguro…

Desculpe amigo, nao entendi? ;X

Dentre as coisas que achei na internet “não foi muita coisa” hash, gostei dessa sua ideia do banco, acho que vou tentar também

Gostei bastante dessa ultima ideia amigo, creio que se conseguir fazer essa implementação do endereço MAC, fica ‘redondo’ com a tabela local para validar a data. Pois o endereço MAC vai cuidar pra não usar o programa por 30 dias em vários pc’s haha

Achei um blog interessante, simples e direto se vc quizer dar uma olhada segue o link
Pegando o Mac Address

Alguma solução?

Capturar eu tenho um erp que uso um gerador de chave criptografada, quando vence a data de uso ele bloqueia o sistema, quando o cliente esta em dia eu mando a chave para ele, e ele mesmo inseri no sistema

private void btGeraChaveActionPerformed(java.awt.event.ActionEvent evt) {
//CRIPTOGRAFA
try {
SimpleDateFormat sdf = new SimpleDateFormat(“dd/MM/yyyy”);
String Nova_Data = sdf.format(txtData.getDate());
String Criptografa = criptografiaBase64Encoder(Nova_Data);
txtChaveGerada.setText(Criptografa);
} catch (Exception e) {
}

private void btDescriptografaActionPerformed(java.awt.event.ActionEvent evt) {
//DESCRIPTOGRAFA
try {
String ChaveGerada = txtValidaChave.getText();
String Descriptografa = descriptografiaBase64Decode(ChaveGerada);
JOptionPane.showMessageDialog(null, Descriptografa);
} catch (Exception e) {
}

Capturar

o cliente inseri aqui a chave gerada.

@kaciocley Eu achei a solução legal, mas eu queria saber como o programa do cliente lida com este código.

Como que o programa sabe que a data é válida e não uma data longa demais criada por um usuário malicioso?

É que do jeito que vc mostrou eu entendi que vc manda o código em Base64 cru pro cliente, só que se for só isso é facinho de burlar. Se for isso mesmo, vc já teve algum caso de usuário tentando gerar o código sozinho?

Eu imaginei uma solução chaves assimétricas.

  1. Vc geraria as chaves publicas e privadas
  2. enviaria o programa pro cliente já com a chave pública
  3. geraria a data e a assinaria com a chave privada
  4. enviaria pro cliente o código no formato <data> + <assinatura>
  5. o programa removeria a parte da data e verificaria a assinatura
  6. Se tudo correr bem, o programa abre

Seria algo assim:

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.time.LocalDate;
import java.util.Base64;

public class App {
  private static final Signature signature;
  private static final KeyPair keyPair;

  static {
    try {
      final KeyPairGenerator generator = KeyPairGenerator.getInstance("DSA");
      generator.initialize(2048);
      keyPair = generator.generateKeyPair();
      signature = Signature.getInstance("SHA256WithDSA");
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  static private String getSignature(LocalDate date) throws Exception {
    signature.initSign(keyPair.getPrivate());
    signature.update(date.toString().getBytes());
    return Base64.getEncoder().encodeToString(signature.sign());
  }

  static private boolean verifySignature(LocalDate date, String encodedSignature) throws Exception {
    signature.initVerify(keyPair.getPublic());
    signature.update(date.toString().getBytes());
    return signature.verify(Base64.getDecoder().decode(encodedSignature));
  }

  static private String getActivationKey(LocalDate date) throws Exception {
    String encodedSignature = getSignature(date);
    String encodedDate = Base64.getEncoder().encodeToString(date.toString().getBytes());
    return encodedDate + "." + encodedSignature;
  }

  public static void main(String... args) throws Exception {
    LocalDate date = LocalDate.now().plusMonths(1);
    String activationKey = getActivationKey(date);

    System.out.println(activationKey);

    // Lá no cliente:

    String[] activationKeyParts = activationKey.split("\\.");
    LocalDate nextDate = LocalDate.parse(new String(Base64.getDecoder().decode(activationKeyParts[0])));

    if (verifySignature(nextDate, activationKeyParts[1])) {
      System.out.println("A data é válida 👍🏾");
    }
  }
}

Será que funcionaria na prática?

EDIT 1:
Percebi que minha ideia com a assinatura na vale de nada :sweat_smile:

Mas veja esta outra ideia onde eu mando tudo encriptado:

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;

public class App {
  private static final KeyPair keyPair;

  private static final Cipher cipher;

  static {
    try {
      final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
      generator.initialize(2048);
      keyPair = generator.generateKeyPair();
      cipher = Cipher.getInstance("RSA");
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
      throw new RuntimeException(e);
    }
  }

  private static String getActivationKey(LocalDate date) throws Exception {
    cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
    byte[] encryptedBytes = cipher.doFinal(date.toString().getBytes());
    return Base64.getEncoder().encodeToString(encryptedBytes);
  }

  private static LocalDate getNextExpirationDate(String activationKey) throws Exception {
    cipher.init(Cipher.DECRYPT_MODE, keyPair.getPublic());
    byte[] decoded = Base64.getDecoder().decode(activationKey);
    return LocalDate.parse(new String(cipher.doFinal(decoded)));
  }

  public static void main(String... args) throws Exception {
    LocalDate date = LocalDate.now().plusMonths(1);

    String activationKey = getActivationKey(date);

    System.out.println(activationKey);

    System.out.println(getNextExpirationDate(activationKey));
  }
}

EDIT 2:
Acho que a primeira ideia era válida sim, só precisei mudar um pouco o código.

1 curtida

boa parceiro vou fazer uns teste aqui!