我想为我的手机应用程序开发一个密钥生成器。目前我正在使用外部服务来完成这项工作,但我有点担心服务可能会在某一天下线,因此我会陷入困境。
身份验证的工作原理。
我喜欢这个并且效果很好,但是,我想从我自己的网站创建自己的“密钥生成服务”。
要求:
有人可以给我一些关于如何实现这一目标的指示吗?我已经涉足了一些java加密,但绝对不是专家,找不到任何能帮助我的东西。
我需要实例化的Java类列表会很有帮助。
答案 0 :(得分:1)
有趣的问题让我对它进行了一些实验。但正如你可能已经猜到的那样,我之前没有这样做过。但也许其他人可以证实我的想法 - 或反驳他们,但请不要贬低;)
我使用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());
}
}
}
答案 1 :(得分:1)
问题是,尽管有足够强大的算法,问题是你如何使用它们,因为如果你以错误的方式组合这些算法或者使用坏种子来处理某些算法,那么弱键(例如它们的长度)你会得到一些不安全的东西。所以经验表明,最好不要尝试自己实现它并冒险犯错误,直到你对密码学理论有足够的信心。
然而另一个答案似乎就是一个很好的例子。