web-dev-qa-db-ja.com

PKIを使用した鍵交換

私は暗号化の分野に不慣れで、PKIキー交換メカニズムを理解するためのサンプルプログラムを試しています。 opensslを使用して自己署名証明書を作成してみました

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.cer

これにより、クライアントプログラムに公開できる証明書ファイルと、クライアントプログラムで暗号化されたテキストを復号化するためにユーザーが使用する秘密キーファイルが得られました。証明書ファイルを使用してプレーンテキストを暗号化できますが、秘密キーの取得で問題が発生します。秘密鍵を鍵ファイルから読み取って復号化で使用するにはどうすればよいですか?.

鍵交換についての私の理解は、自己署名またはCAから取得した公開鍵と秘密鍵を持っていることです。メッセージを送信するアプリケーション(送信者)に公開鍵を公開します。送信者は公開鍵を使用して対称鍵を暗号化し、受信者は秘密鍵を使用してメッセージを復号化するため、双方は対称鍵を交換して双方向の暗号化をさらに進めます。

以下を使用して秘密キーを抽出しようとしている間Javaコード

public class RSAToy {


    private static final String BEGIN_RSA_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n"
            + "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDW6ofjl8o8sjGg\n"
            + "ANqLneMcrq+xUYVRnKT1mGtboMYHJqtgNIbCzMo4Ym4Uw5+m1JEa2fxbcExp1JAK\n"
            + "A3Cmih+KaJ/gjyaJDKHrTuRN7hs4oSo6aPTIAW3euuqWH7xrFOIvXRRIqRWu4oir\n"
            + "xEjjyQ2IxqkPssf+AUAkz9DiH6phGIaXHXocIsCSEssZWkYd7WZ0HYL3Bfz+W4aY\n"
            + "+PfKDwflMLknsWOkmzc8N+i4Bac3IxOuFhwmg3y2YQq//ZkkaJv3OVIjj6v2OuRY\n"
            + "vgfrPs9dwkshloxp8HRDlA5upXiBiv3JOawbkBUs+bmxzjTNT+vyliKb4qq9ZCAF\n"
            + "ikV5BKazAgMBAAECggEADao137O8CSXvX9QOEUiFs0IsK6MaTfkex/rcAKR1UukT\n"
            + "hndwhhxNU052310c3pevbjyj/hBi22vHiMt1MzGfFcbXO4j+k0I5XWPTwly8YFpm\n"
            + "+/XGcp0cpkfOOKNl8I0QYKCTdJdDqK4AsKM3WzxiXur6vuPIMY9Uy8Jm7qnCxI+T\n"
            + "xoYW857hX9caDvDS+YyMzHFHfcuqI0//4AzjgxgIqy8D0w9u4Xr61mAsLYNsXAUt\n"
            + "ZPOXoI8KhQ7DAAYzmY3OnBRr3fQbM2yXVxdW9Tv6bhmFrpuicUHfMRJrnjzK1b4O\n"
            + "nPtn5542rVzCXe6FWu1c98Gw0S+oo3G8gfgg/IpukQKBgQD4cnXrMGV2ETE3rWjD\n"
            + "drEo0pGJ8UCAwl08xBRY5dlK6SkfsnMOiZhQIsFLqMvknEmYNarWdu4Bmu3lgoo1\n"
            + "/JO0UGUifbklhDTQoy7q12jzCLMMQMSm5ziTCehJ2lOMI+Z+Gd+AQD9ltCUBCQrR\n"
            + "s8YhAR8TH5aDtb2kkohRrDufKwKBgQDdcx2LvnjaR1lB9MQ85snTx2LQt26ewyRd\n"
            + "2zxBBQtNGQvmP0mj3t/88tHu+MPQCCvHpFiPdcs7VN/SEfE6vw9R0YY6b/YIKelm\n"
            + "uj9t5Ar2EZtUvbiVCYyKXAl5tgXNAESTP8LDidhQ41UjJS0ZaVwXbCwDVDZqS4NY\n"
            + "JGSeq9SSmQKBgQCGQ40YOcJLKQVZGnyoTUd2UT1Xt6ntK5ypjymT1Ts1sYWI3K4z\n"
            + "KAbJH88oLSNq+08GU9JsLj93XJu90WsRu9qyslPFbP4WmTjVm6pqPVk5JfVk5Meh\n"
            + "jwlS5SLEbpmB/ZC9wl8O1ymrs8vfoFxZcXbcNTfu5L45lYjUHGBRCuv5mwKBgBN6\n"
            + "AGs+AVsRU2RdprTEh5O8wZAh0fTcrOIkWhRN4USSo11Iy61B+OlCYfxmnLI7Rb51\n"
            + "UeSsM4ewW08ajODh1PMZPnj9R+JH7WM/ljyQBfbGbabyWL2i7V1t4td1juUM1Psu\n"
            + "bG7OPNxAYkiJCIJnpdXZibVxPqfypEaoTME306ZhAoGBAO9E1RbKR+9p/h7xzXPE\n"
            + "0vFyN0ItW2Mu3ESE4VRplYx4ht/zZ4gBJMHLNNQCk3IQGflizJ6+On74z6RnYxAy\n"
            + "jiF9zLqj8NKy24wrWithYepG4C0JL6xg2k3gYLxyuccXak06D0ABDxnwJcXrZvmq\n"
            + "zuhsR8X+g3gxaGr7dTgMcZ2J\n"
            + "-----END PRIVATE KEY-----";


    public static void main(String[] args) throws Exception {

        // Remove the first and last lines

        String privKeyPEM = BEGIN_RSA_PRIVATE_KEY.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
        privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
//        System.out.println(privKeyPEM);

        // Base64 decode the data

        byte [] encoded = Base64.decodeBase64(privKeyPEM);

        // PKCS8 decode the encoded RSA private key

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);

//        RSAPrivateKeySpec keySpec = new R
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PrivateKey privKey = kf.generatePrivate(keySpec);

        // Display the results

        System.out.println(privKey);
    }
}

私は得ています

Exception in thread "main" Java.security.spec.InvalidKeySpecException: Java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=111, too big.
    at Sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source)

それを修正して秘密キーを抽出し、エンコードされたメッセージを復号化するにはどうすればよいですか。どんな助けでも大歓迎です。

3
Vijay Selvaraj

OpenSSLが秘密鍵を作成するときは、独自の形式を使用します。実際には、 PKCS#1 で説明されている生のASN.1ベースの形式です。これは PKCS#8 ではなく、これはその形式のラッパーです。

秘密鍵は次のようにPKCS#8形式に変換できます。

openssl pkcs8 -in privateKey.key -topk8 -nocrypt -out privateKey.pk8

「-nocrypt」オプションは、PKCS#8がオプションで秘密鍵のパスワードベースの暗号化をサポートするためです。あなたは付け加えられます -outform DER PEMエンコードを回避します(「PEM」はBase64と1組のヘッダーであり、コードから削除します)。

3
Thomas Pornin

Windowsでも解析したい場合は、

keyStr.replaceAll("(-+BEGIN RSA PRIVATE KEY-+\\r?\\n|-+END RSA PRIVATE KEY-+\\r?\\n?)", "");

dER文字列に置き換えます。

0
Rik

X509証明書を作成していますが、PKCS8形式の鍵をインポートしようとしています。エクスポートされたキーには互換性がありません。 PKCS8 DER/PEM(Javaのどちらが必要か)に応じて)をエクスポートするか、コードを変更してx509キーをインポートする必要があります。

0
Polynomial