在JAVA中构建“激活密钥”生成器

时间:2010-05-24 07:39:21

标签: java authentication encryption cryptography

我想为我的手机应用程序开发一个密钥生成器。目前我正在使用外部服务来完成这项工作,但我有点担心服务可能会在某一天下线,因此我会陷入困境。

身份验证的工作原理。

  1. 存储在手机上的公钥。
  2. 当用户请求密钥时,“电话ID”被发送到“密钥生成服务”,并且加密的密钥被返回并存储在许可证文件中。
  3. 在手机上,我可以使用方法getPhoneId()检查该密钥是否适用于当前手机,我可以使用当前手机检查并授予或不授予对功能的访问权限。
  4. 我喜欢这个并且效果很好,但是,我想从我自己的网站创建自己的“密钥生成服务”。

    要求:

    1. 公钥和私钥
    2. 加密:( Bouncy Castle)
    3. 用JAVA撰写
    4. 必须支持getApplicationId()(以便许多应用程序可以使用相同的密钥生成器)和getPhoneId()(以从加密的许可证文件中获取电话ID)
    5. 我希望能够将ApplicationId和PhoneId发送到服务以生成许可证密钥。
    6. 有人可以给我一些关于如何实现这一目标的指示吗?我已经涉足了一些java加密,但绝对不是专家,找不到任何能帮助我的东西。

      我需要实例化的Java类列表会很有帮助。

2 个答案:

答案 0 :(得分:1)

有趣的问题让我对它进行了一些实验。但正如你可能已经猜到的那样,我之前没有这样做过。但也许其他人可以证实我的想法 - 或反驳他们,但请不要贬低;)

我使用asymmetric algorithmRSA来签署一个字符串,该字符串包含必须匹配的所有数据才能生效。此签名与公钥一起存储,以便在不需要访问服务器的情况下进行验证。

表示为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());
    }

  }
}

答案 1 :(得分:1)

问题是,尽管有足够强大的算法,问题是你如何使用它们,因为如果你以错误的方式组合这些算法或者使用坏种子来处理某些算法,那么弱键(例如它们的长度)你会得到一些不安全的东西。所以经验表明,最好不要尝试自己实现它并冒险犯错误,直到你对密码学理论有足够的信心。

然而另一个答案似乎就是一个很好的例子。