在我的Android应用程序中,我想实现Diffie-Hellman协议,以便在两个用户之间生成一个共同的秘密。
我所做的是以下内容:当第一个用户向第二个用户发送友情请求时,应用程序会生成一个密钥对,将公共密钥对存储在远程数据库中,私有密钥对存储在本地数据库中。
以下是第一部分的代码:
generateKeys();
localDB.insertPrivateKey(userId, entityId, privateKey);
remoteDB.insertFirstPublicKey(userId, entityId, publicKey);
generateKeys方法如下:
private void generateKeys() {
try {
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
keyPairGenerator.initialize(1024);
final KeyPair keyPair = keyPairGenerator.generateKeyPair();
privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
} catch (Exception e) {
e.printStackTrace();
}
}
当第二个用户接受请求时,会生成另一个密钥对,再次将私钥存储在本地数据库中,并将公共存储在远程数据库中。然后,它从远程数据库中获取第一个用户的公钥,将其转换回PublicKey并生成公共密钥。
以下是第二部分的代码:
generateKeys();
localDB.insertPrivateKey(userId, entityId, privateKey);
remoteDB.insertSecondPublicKey(entityId, userId, publicKey);
String stringFirstPubKey = remoteDB.fetchFirstKey(entityId, userId);
PublicKey firstPubKey = stringToPublicKey(stringFirstPubKey);
byte[] commonSecret = generateCommonSecret(firstPubKey);
stringToPublicKey如下:
private PublicKey stringToPublicKey(String stringPubK) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] pubK = Base64.decodeBase64(stringPubK);
KeyFactory keyFactory = KeyFactory.getInstance("DH");
EncodedKeySpec keySpec = new X509EncodedKeySpec(pubK);
return keyFactory.generatePublic(keySpec);
}
and generataCommonSecret:
private byte[] generateCommonSecret(PublicKey firstPubKey) {
try {
final KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(privateKey);
keyAgreement.doPhase(firstPubKey, true);
byte[] secretKey = adjustKeyLenght(keyAgreement.generateSecret());
return secretKey;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
同样在存储密钥时,我将它们转换为String,其中包含以下内容:
String stringPubK = Base64.encodeBase64String(publicKey.getEncoded());
在generateCommonSecret
中执行以下行时keyAgreement.doPhase(firstPubKey, true);
我得到了这个例外
java.security.InvalidKeyException: DHPublicKey not for this KeyAgreement!
at com.android.org.bouncycastle.jcajce.provider.asymmetric.dh.KeyAgreementSpi.engineDoPhase(KeyAgreementSpi.java:101)
at javax.crypto.KeyAgreement.doPhase(KeyAgreement.java:383)
有人可以帮我找到问题吗?奇怪的是,如果我尝试在单个java类中执行此操作,而不存储和检索键,则可以正常工作。