Создание генератора ключа активации в JAVA - PullRequest
5 голосов
/ 24 мая 2010

Я хочу разработать генератор ключей для моих телефонных приложений. В настоящее время я использую внешнюю службу для выполнения этой работы, но меня немного беспокоит, что однажды эта служба может отключиться, поэтому я буду в некотором затруднении.

Как работает аутентификация.

  1. Открытый ключ хранится на телефоне.
  2. Когда пользователь запрашивает ключ, в службу генерации ключей отправляется «идентификатор телефона», а зашифрованный ключ возвращается и сохраняется в файле лицензии.
  3. На телефоне я могу проверить, является ли ключ для текущего телефона, используя метод getPhoneId (), который я могу проверить с текущим телефоном и предоставить или не предоставить доступ к функциям.

Мне это нравится, и оно работает хорошо, однако я хочу создать свою собственную "Службу генерации ключей" со своего собственного веб-сайта.

Требования:

  1. Открытый и закрытый ключ
  2. Шифрование: (Надувной замок)
  3. Написано на JAVA
  4. Должен поддерживать getApplicationId () (чтобы многие приложения могли использовать один и тот же генератор ключей) и getPhoneId () (чтобы получить идентификатор телефона из зашифрованного файла лицензии)
  5. Я хочу иметь возможность отправить ApplicationId и PhoneId в службу для генерации лицензионного ключа.

Может кто-нибудь дать мне несколько советов о том, как это сделать? Я немного поигрался с Java-шифрованием, но определенно не эксперт и не могу найти ничего, что могло бы мне помочь.

Будет полезен список классов Java, которые мне нужно будет создать.

Ответы [ 2 ]

1 голос
/ 20 июня 2010

Проблема в том, что, хотя существуют достаточно сильные алгоритмы, проблема в том, как вы их используете, потому что, если вы комбинируете эти алгоритмы неправильно или используете плохие начальные значения для некоторых алгоритмов, слабые ключи (например, их длина) вы в конечном итоге с чем-то, что небезопасно.Итак, опыт говорит, что лучше не пытаться реализовать это самостоятельно и рисковать ошибками, пока вы не будете достаточно уверены в теории криптологии.

Однако другой ответ, кажется, дает хороший пример.

1 голос
/ 16 июня 2010

Интересный вопрос, который заставил меня немного поэкспериментировать с ним. Но, как вы уже догадались, я раньше этого не делал. Но, может быть, кто-то еще может подтвердить мои мысли - или опровергнуть их, но, пожалуйста, не понижая голос;)

Я бы использовал асимметричный алгоритм , такой как RSA , чтобы подписать строку, которая состоит из всех данных, которые должны соответствовать, чтобы быть действительными. Эта подпись хранится вместе с открытым ключом для проверки ее без необходимости доступа к серверу.

Выражается как код Java, это будет выглядеть следующим образом (на основе Signature Sign and Verify ):

import java.security.*;

public class Main {
  public static void main(String args[]) throws Exception {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

    // our server, imagine it's a webservice
    KeyServer server = new KeyServer(42);

    // init client with a copy of public key from server
    KeyClient client = new KeyClient(server.getPublicKey());

    // create string that identifies phone and application
    byte[] data = (getPhoneId() + ":" + getApplicationId()).getBytes("utf-8");

    // send data to server for signature creation
    byte[] digitalSignature = server.signData(data);

    // verify on client side
    System.out.println("verified = " + client.verifySig(data, digitalSignature));

    // bad data
    byte[] wrongData = ("anotherPhoneId" + ":" + getApplicationId()).getBytes("utf-8");
    System.out.println("verified = " + client.verifySig(wrongData, digitalSignature));

    // bad signature
    digitalSignature[5] = (byte) 0xff;
    System.out.println("verified = " + client.verifySig(data, digitalSignature));
  }

  private static String getPhoneId() {
    return "somephone";
  }

  private static String getApplicationId() {
    return "someapp";
  }

  public static class KeyClient {

    private PublicKey _publicKey;
    private Signature _signer;

    public KeyClient(PublicKey publicKey) {
      if (publicKey == null) {
        throw new NullPointerException("publicKey");
      }
      _publicKey = publicKey;

      try {
        _signer = Signature.getInstance("SHA1withRSA");
      } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("failed to get Signature", e);
      }
    }

    public boolean verifySig(byte[] data, byte[] sig) throws Exception {
      synchronized (_signer) {
        _signer.initVerify(_publicKey);
        _signer.update(data);
        return (_signer.verify(sig));
      }
    }
  }

  public static class KeyServer {

    private KeyPair _keyPair;
    private Signature _signer;

    public KeyServer(int seed) {
      try {
        _keyPair = generateKeyPair(seed);
      } catch (Exception e) {
        throw new RuntimeException("failed to generate key pair for seed " + seed, e);
      }

      try {
        _signer = Signature.getInstance("SHA1withRSA");
      } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("failed to get Signature", e);
      }
    }

    public PublicKey getPublicKey() {
      return _keyPair.getPublic();
    }

    public byte[] signData(byte[] data) throws InvalidKeyException, SignatureException {
      synchronized (_signer) {
        _signer.initSign(_keyPair.getPrivate());
        _signer.update(data);
        return (_signer.sign());
      }
    }

    private KeyPair generateKeyPair(long seed) throws Exception {
      KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("RSA");
      SecureRandom rng = SecureRandom.getInstance("SHA1PRNG", "SUN");
      rng.setSeed(seed);
      keyGenerator.initialize(2048, rng);
      return (keyGenerator.generateKeyPair());
    }

  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...