有趣的問題讓我試驗了一下。但是,正如你可能已經猜到的那樣,我之前沒有這樣做過。但也許別人可以證實我的想法 - 或反駁他們,但請不要downvoting;)
我會使用一個asymmetric algorithm如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());
}
}
}
@jax - 你有成功研究這個問題嗎?我也在尋找一個安全的激活密鑰生成器。 – Stevko 2010-06-09 22:00:20
是的,我現在正在拋棄它 - 我可以告訴你這是#$%$中的一大痛苦。 – jax 2010-06-10 04:33:08
關於這個話題的信息很少,當你問一個問題的時候,人們告訴你,如果你不明白你不應該這樣做 - 我認爲這是完全荒謬的 - 人們如何學習!一旦我完成我的API,我可能會從doridprofessor.com出售它。但是,如果想讓您擁有自己的產品,請查看andappstore.com,他們已經爲您提供了在線服務。你可以看看他們的代碼並對其進行逆向工程。 Commons Base64類對於將二進制許可證編碼爲文本可讀形式也非常有用。 – jax 2010-06-10 04:34:05