3

Web サイトに記載されている手順に従って、 gdcmanonで使用するために OpenSSL を使用して公開/秘密キーのペアを生成した状況があります。具体的には、次のコマンドを使用して gdcmanon のキーを生成しました

$ openssl genrsa -out CA_key.pem
$ openssl req -new -key CA_key.pem -x509 -days 365 -out CA_cert.cer

その後、彼らの指示に従い、次を使用してファイルを暗号化することができました

gdcmanon -c CA_cert.cer -e original.dcm original_anonymized.dcm

を使用してファイルを復号化します

gdcmanon -k CA_key.pem -d original_anonymized.dcm orginal_deanonymized.dcm

次に、そのキーを使用して、対応する DICOM ファイルの情報を Java でデコードしたいと考えています。Javaでキーを取得することさえ苦労した後、このページを見つけ、次の呼び出しでJavaプログラムがクラッシュしないキーを作成することができました

openssl pkcs8 -topk8 -inform PEM -outform DER -in CA_key.pem -out CA_key.pkcs8.pem -nocrypt

以上のことと、たくさん読んだ後、次の Java コードを作成しました。

public static String decode(byte[] encryptedData) {
    Key key = readPEMKey(new File("CA_key.pkcs8.pem"));
    //Key key = readPEMKey(new File("CA_key.pem"));
    try {
        Cipher c = Cipher.getInstance("RSA");
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decValue = c.doFinal(encryptedData);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

private static Key readPEMKey(File key) {
    DataInputStream dis = null;
    BufferedReader reader = null;
    try {
        /*
        reader = new BufferedReader(new FileReader(key));
        String privKeyPEM = "";
        String line;
        while ((line = reader.readLine()) != null) {
            if (!line.equals("-----BEGIN RSA PRIVATE KEY-----") && !line.equals("-----END RSA PRIVATE KEY-----"))
            privKeyPEM += line + "\n";
        }
        byte[] encoded = new BASE64Decoder().decodeBuffer(privKeyPEM);
        */

        dis = new DataInputStream(new BufferedInputStream(new FileInputStream(key)));
        byte[] encoded = new byte[(int) key.length()];
        dis.readFully(encoded);

        // PKCS8 decode the encoded RSA private key
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PrivateKey privKey = kf.generatePrivate(keySpec);
        return privKey;
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        if (reader != null) {try {reader.close();} catch (Exception e) {e.printStackTrace();}}
        if (dis != null) {try {dis.close();} catch (Exception e) {e.printStackTrace();}}
    }
    return null;
}

さまざまな方法でデコード用の秘密鍵を読み取って処理する方法をいくつか試しましたが (コメントアウトされたセクションからわかるように)、encryptedData によって復号化するソリューションをまだ見つけていません。RSA アルゴリズムで Cipher を使用すると、次のスタック トレースが得られます。

javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes
at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at my.app.decode(Application.java:124)

これは行 byte[] decValue = c.doFinal(encryptedData); で失敗します。

AESアルゴリズムでCipherを使用すると、次のスタックトレースが得られます

java.security.InvalidKeyException: No installed provider supports this key: sun.security.rsa.RSAPrivateCrtKeyImpl
at javax.crypto.Cipher.a(DashoA13*..)
at javax.crypto.Cipher.init(DashoA13*..)
at javax.crypto.Cipher.init(DashoA13*..)
at my.app.Application.decode(Application.java:123)

これは c.init(Cipher.DECRYPT_MODE, key); 行で失敗します。

Java 6 用の JCE を既にインストールしています (これを使用しています)。何が間違っているのかわかりません。誰かが私を正しい方向に向けてください。

ありがとう

アップデート

私はこれに多くの作業をしてきました.Bouncy Castleも試しましたが、まだ結果はありません. これは、Bouncy Castle を使用した最初の試みです。

BufferedReader reader = new BufferedReader(new FileReader(new File("CA_key.pem")));
PEMParser parser = new PEMParser(reader);
PEMKeyPair keyPair = (PEMKeyPair)parser.readObject();
AsymmetricKeyParameter privKeyParams = PrivateKeyFactory.createKey(keyPair.getPrivateKeyInfo());
AsymmetricKeyParameter publicKeyParams = PublicKeyFactory.createKey(keyPair.getPublicKeyInfo());
parser.close();

RSAEngine e = new RSAEngine();
e.init(false, publicKeyParams);
byte[] decValue = e.processBlock(encryptedData, 0, encryptedData.length);

ここでも、processBlock メソッド org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher で例外が発生します。これは私が以前に抱えていた問題と同じだと思います。gdcmanon ツールは CA_key.pem ファイルだけでこの文字列を明確に復号化できるため、これは唯一の入力 (復号化するファイル以外) であるため、ここでは本当に途方に暮れています。gdcmanon のソースをいろいろ調べてみましたが、どうやら AES 256 キーを使用しているように見えますが、生成した RSA キーからそれを取得する方法がわかりません。誰かが私を正しい方向に向けることができますか?

編集

gdcmanon のソースをさらに調べてみたところ、Cryptographic Message Syntax (CMS) を使用しているようです。これは私にはまったく新しいことですが、BC には CMS 関連のクラスがたくさんあるようです。具体的には、gdcmanon は PKCS7_dataDecode と呼ばれる OpenSSL メソッドを使用してデータを復号化しています。Java でこれを行う方法の良い例は見つかりませんでした。何か案は?

ありがとう

4

1 に答える 1

1

苦労のトンの後、私は最終的に動作するように見える次のコードを持っています。誰かが BC なしでこれを行う方法を教えてくれたら、それは素晴らしいことですが、今のところ、うまくいくことを嬉しく思います。

public static String decode(byte[] encryptedData, String keyFile) {
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new FileReader(new File(keyFile)));
        PEMParser parser = new PEMParser(reader);
        PEMKeyPair keyPair = (PEMKeyPair)parser.readObject();
        AsymmetricKeyParameter privKeyParams = PrivateKeyFactory.createKey(keyPair.getPrivateKeyInfo());
        parser.close();

        CMSEnvelopedData data = new CMSEnvelopedData(encryptedData);
        RecipientInformationStore recipients = data.getRecipientInfos();

        Iterator it = recipients.getRecipients().iterator();

        if (it.hasNext()) {
            RecipientInformation recipient = (RecipientInformation)it.next();
            byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(privKeyParams));
            String decryptedValue = new String(recData);
            return decryptedValue;
        }
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        if (reader != null) {try {reader.close();} catch (Exception e) {e.printStackTrace();}}
    }
    return null;
}
于 2013-04-17T20:12:42.887 に答える