2015-09-28 196 views
2

加密和解密成功時,加密與公鑰與私鑰解密:C#RSA加密與私鑰

C#加密基於公鑰(成功)

public string EncryptData(string data) { 

     RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 
     rsa.FromXmlString(xml); //public key 

     var cipher = rsa.Encrypt(Encoding.UTF8.GetBytes(data), false); 

     return Convert.ToBase64String(cipher); 
    } 

Java的解密與私人鑰匙(成功)

public static void decrypt() throws Exception{ 
    byte[] modulusBytes = Base64.getDecoder().decode(mod); 
    byte[] dByte = Base64.getDecoder().decode(d); 

    BigInteger modulus = new BigInteger(1, (modulusBytes)); 
    BigInteger exponent = new BigInteger(1, (dByte)); 

    RSAPrivateKeySpec rsaPrivKey = new RSAPrivateKeySpec(modulus, exponent); 
    KeyFactory fact = KeyFactory.getInstance("RSA"); 
    PrivateKey privKey = fact.generatePrivate(rsaPrivKey); 

    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
    cipher.init(Cipher.DECRYPT_MODE, privKey); 

    byte[] cipherData = Base64.getDecoder().decode(cipherByte); 
    byte[] plainBytes = cipher.doFinal(cipherData); 


    System.out.println(new String(plainBytes)); 
} 

問題是在這裏

當與私鑰和java C#加密與公開密鑰壞填充錯誤解密發生:

C#加密的私人密鑰(失敗)

public stringEncryptData(string data) { 

     RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 
     rsa.FromXmlString(xml); //private key 

     var cypher = rsa.Encrypt(Encoding.UTF8.GetBytes(data), false); 

     return Convert.ToBase64String(cypher); 
    } 

java的解密帶公鑰(失敗)

public static void decryptPublic() throws Exception{ 

    byte[] modulusBytes = Base64.getDecoder().decode(mod); 
    byte[] expBytes = Base64.getDecoder().decode(exp); 

    BigInteger modulus = new BigInteger(1, (modulusBytes)); 
    BigInteger exponent = new BigInteger(1, (expBytes)); 

    RSAPublicKeySpec pubKey = new RSAPublicKeySpec(modulus, exponent); 
    KeyFactory fact = KeyFactory.getInstance("RSA"); 
    PublicKey publicKey = fact.generatePublic(pubKey); 
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
    cipher.init(Cipher.DECRYPT_MODE, publicKey); 


    byte[] cipherData = Base64.getDecoder().decode(cipherByte); 
    byte[] plainBytes = cipher.doFinal(cipherData); 

    System.out.println(new String(plainBytes)); 
} 

我知道公鑰應該用來做解密加密和私鑰。但在我的情況下,我需要將公鑰發送給多個客戶端,以解密由其私鑰加密的文本。除客戶端外,其他人不應閱讀文本。 任何人都可以看到我的代碼有什麼問題,或者建議更好的解決方案來解決我的問題。

+0

用公鑰加密並用私鑰解密。將私鑰的副本提供給需要副本解密的每個人,但不要嘗試顛倒算法。 – WDS

+1

@WDS正如我的回答所述,分配私鑰也是一個非常糟糕的主意,因爲您完全無法控制其他方可能與誰共享密鑰,並且極大地增加了處理被盜用密鑰的難度。 – Iridium

+0

@CY LIM:你的加密和解密方法應該是鏡像的,這意味着如果你在你的JAVA解密函數中使用PKCS1填充('Cipher cipher = Cipher.getInstance(「RSA/ECB/PKCS1Padding」)'),你應該也使用PKCS1填充你的C#加密函數'var cypher = rsa.Encrypt(Encoding.UTF8.GetBytes(data),false);'用'var cypher = rsa.Encrypt(Encoding.UTF8.GetBytes(data),RSAEncryptionPadding.Pkcs1) ;'。 https://msdn.microsoft.com/en-us/library/mt132684%28v=vs.110%29.aspx – godvsdeity

回答

1

只有在使用(安全)填充方案時,RSA加密纔是安全的。 RSA加密方案已由RSA實驗室(現爲EMC的一部分)在PKCS#1標準中進行了規定()。這些已被複制到RFC中,如RFC 3447: Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1

對於這個文件的目的,加密方案由 加密操作和解密操作,其中 加密操作從消息產生密文有 接收者的RSA公鑰,並且解密操作恢復來自密文的 消息與收件人的相應RSA 私鑰

因此用私鑰加密是一個未定義的操作。


那麼現在要做的:

  • 安全而不是分發公鑰的私鑰
  • 生成密鑰對和安全運輸公鑰發送
  • 如果您需要認證/完整性而不是機密性,請使用簽名生成而不是加密

而且,無論你做什麼,都要讀入公鑰基礎結構(PKI)。這是一個非常有伸縮性的主題,在你應用之前你需要了解它。

-1

加密用私鑰/用公鑰解密在RSA合法的操作,然而用於保護數據,它將代替用於驗證數據的完整性的來源。在這種情況下,加密操作通常被稱爲「簽名」。

使用私鑰加密以保護數據,因爲您描述的是不安全的,所以它不容易完成的事實可能是故意的,並且旨在防止錯誤地使用算法。

按照註釋中的建議將您的私鑰分配給客戶也是不明智的,因爲您無法控制他們可以將密鑰傳遞給誰(意外或其他方式)。

如果您希望對數據進行加密以便可以由多個不同的方進行解密,那麼您應該讓他們各自爲您提供自己的公鑰,並使用它爲每個客戶端分別加密數據。

+0

第一句話是非常錯誤的; RSA加密*未定義*使用私鑰時。你可以使用私鑰來進行模冪運算,但這就是它。 –

+1

@MaartenBodewes:從上下文中取出一個單詞是毫無意義的。只要閱讀段落中剩餘的一句話就可以提供預期的意義。 –

+0

@JamesKPolk不,對不起,我不同意。 PKCS#1標準甚至使用模冪的不同名稱來表示簽名與加密不同。談到簽名生成時的RSA加密只會增加混淆。 –