3

私の Android アプリケーションでは、2 人のユーザー間で共通の秘密を生成するために Diffie-Hellman プロトコルを実装したいと考えています。

私がしていることは次のとおりです: 最初のユーザーが 2 番目のユーザーにフレンドシップ リクエストを送信すると、アプリはキー ペアを生成し、公開キーをリモート データベースに、非公開キーをローカル データベースに保存します。

この最初の部分のコードは次のとおりです。

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();
        }
    }

2 番目のユーザーが要求を受け入れると、別のキー ペアが生成され、再びプライベート キーがローカル データベースに格納され、パブリック キーがリモート データベースに格納されます。次に、リモート データベースから最初のユーザーの公開鍵を取得し、それを PublicKey に変換して、共通の秘密を生成します。

2番目の部分のコードは次のとおりです。

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);
}

そして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 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 クラスでこれを実行しようとすると、正常に動作することです。

4

0 に答える 0