2010-05-24 84 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

是,雖然有算法,它是足夠強大的,問題是你如何使用它們的問題,因爲如果你將這些算法以錯誤的方式結合起來,或者對某些算法使用糟糕的種子,那麼弱鍵(例如,它們的長度)會導致某些不安全的結果。所以經驗表明,最好不要嘗試自己實現它,冒着錯誤直到你對密碼學理論足夠有信心。

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