2013-04-16 51 views
2

我有這樣一種情況,即我使用OpenSSL生成了一個公鑰/私鑰對,以便按照其網站上列出的說明與gdcmanon一起使用。具體來說,我用下面的命令來生成我的鑰匙了gdcmanon使用OpenSSL密鑰進行Java加密

$ 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 

加密文件及decrpyt使用

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

然後我想使用該鍵來解碼Java中相應DICOM文件中的一些信息。甚至拿到鑰匙在Java中掙扎之後,我發現this頁,並能作出這樣不會引起我的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; 
} 

,但是,我還沒有找到解密,將加密數據解密。如果我使用一個密碼與RSA算法得到以下堆棧跟蹤

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) 

這失敗在該行字節[] decValue = c.doFinal(的EncryptedData);

,如果我使用的密碼使用AES算法得到以下堆棧跟蹤

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) 

這(Cipher.DECRYPT_MODE,鍵)未能在該行c.init;

我已經安裝了JCE for Java 6(我正在使用)。我不知道我做錯了什麼。有人可以請我指出正確的方向。

感謝

UPDATE

我一直對這個有很多,並嘗試充氣城堡,以及沒有結果呢。這是我第一次嘗試使用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一個例外:輸入太大的RSA密碼。 我認爲這是我以前的問題。在這裏我真的很茫然,因爲gdcmanon工具可以用CA_key.pem文件清楚地解密這個字符串,因爲這是唯一的輸入(除了要解密的文件之外)。我一直在gdcmanon源代碼中尋找很多東西,它看起來好像使用了AES 256密鑰,但我不明白我是如何從我生成的RSA密鑰中獲得的。有人可以請指點我正確的方向嗎?

編輯

我已經經歷了gdcmanon源就更多了,它看起來像他們使用加密消息語法(CMS)。這對我來說是全新的,但看起來BC有一大堆與CMS相關的類。具體來說,gdcmanon使用名爲PKCS7_dataDecode的OpenSSL方法來解密數據。我還沒有找到關於如何在Java中執行此操作的好例子。有任何想法嗎?

感謝

+0

2048位RSA私鑰無法解密超過256個字節的數據,所以您的'encryptedData'參數太大。你當然不應該爲你的密碼使用AES算法,所以你可以忽略你的其他錯誤。我會專注於理解爲什麼你的解密輸入大於預期。 –

+0

根據gdcmanon教程我以爲我做了一個AES密鑰,但老實說我不確定。我對這個級別的密碼很陌生,所以我不確定我做錯了什麼。我知道gdcmanon可以使用CA_key.pem文件正確解密這條消息,因爲這是我認爲我需要的唯一信息。 – Jon

回答

0

奮力一噸後,我終於有了這似乎工作,下面的代碼。如果有人能告訴我一種沒有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; 
} 
相關問題