2015-09-28 241 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加密只会增加混淆。 –