2010-05-24 24 views
5

我想为我的手机应用程序开发密钥生成器。目前我正在使用外部服务来完成这项工作,但我有点担心该服务可能会在一天内脱机,因此我会陷入困境。在JAVA中构建“激活密钥”生成器

身份验证如何工作。

  1. 存储在手机上的公钥。
  2. 当用户请求密钥时,'电话ID'被发送到“密钥生成服务”,并且加密的密钥被返回并存储在许可证文件内。
  3. 在手机上,我可以使用getPhoneId()方法检查当前手机的密钥是否可用,可以使用当前手机进行检查并授予或不授予对功能的访问权限。

我喜欢这样,它运作良好,但是,我想从我自己的网站创建自己的“密钥生成服务”。

要求:

  1. 公钥和私钥
  2. 加密:(充气城堡)
  3. 用Java编写的
  4. 必须支持getApplicationId()(让许多应用程序可以使用相同的密钥生成器)和getPhoneId()(从加密的许可证文件中获取手机ID)
  5. 我希望能够发送ApplicationId和Phone Id到许可证密钥生成服务。

有人可以给我一些关于如何完成这一点的指针吗?我已经涉猎了一些java加密,但绝对不是专家,找不到任何帮助我的东西。

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

+0

@jax - 你有成功研究这个问题吗?我也在寻找一个安全的激活密钥生成器。 – Stevko 2010-06-09 22:00:20

+0

是的,我现在正在抛弃它 - 我可以告诉你这是#$%$中的一大痛苦。 – jax 2010-06-10 04:33:08

+1

关于这个话题的信息很少,当你问一个问题的时候,人们告诉你,如果你不明白你不应该这样做 - 我认为这是完全荒谬的 - 人们如何学习!一旦我完成我的API,我可能会从doridprofessor.com出售它。但是,如果想让您拥有自己的产品,请查看andappstore.com,他们已经为您提供了在线服务。你可以看看他们的代码并对其进行逆向工程。 Commons Base64类对于将二进制许可证编码为文本可读形式也非常有用。 – jax 2010-06-10 04:34:05

回答

1

有趣的问题让我试验了一下。但是,正如你可能已经猜到的那样,我之前没有这样做过。但也许别人可以证实我的想法 - 或反驳他们,但请不要downvoting;)

我会使用一个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

是,虽然有算法,它是足够强大的,问题是你如何使用它们的问题,因为如果你将这些算法以错误的方式结合起来,或者对某些算法使用糟糕的种子,那么弱键(例如,它们的长度)会导致某些不安全的结果。所以经验表明,最好不要尝试自己实现它,冒着错误直到你对密码学理论足够有信心。

但是,其他答案似乎是一个很好的例子。