RSA私钥加密,公钥解密算法(请看详细再回答,不会的帮顶下,谢谢)

Profiteerchen 2009-05-31 09:59:17
各位达人,小弟最近在做项目时候遇到一个关于RSA加密解密的问题。大家都知道.NET库提供的RSACryptoServiceProvider类只支持公钥加密,私钥解密,而现在我遇到的事情是需要私钥加密公钥解密。而我所做的只是公钥解密(公私钥对是java生成的,只提供给我公钥)。针对这个问题,我也在网上找了一些例子,但是还是没有实现。我在网上找到了一个C#写的BigInteger类,并且按照

/// <summary>
        /// 通过公钥解密
        /// </summary>
        /// <param name="dataBytes">待解密字符数组</param>
        /// <returns>解密结果</returns>
        public string DecryptByPublicKey(byte[] dataBytes, byte[] keyN, byte[] keyE)
        {
            //大整数N
            BigInteger biN = new BigInteger(keyN);
            //公钥大素数
            BigInteger biE = new BigInteger(keyE);
            //解密
            return DecryptBytes(dataBytes, biE, biN);
        }

/// <summary>
        /// 解密字符数组
        /// </summary>
        /// <param name="dataBytes">待解密字符数组</param>
        /// <param name="KeyNum">密钥大素数</param>
        /// <param name="nNum">大整数N</param>
        /// <returns>解密结果</returns>
        private string DecryptBytes(byte[] dataBytes, BigInteger KeyNum, BigInteger nNum)
        {
            int len = dataBytes.Length;
            int len1 = 0;
            int blockLen = 0;
            if (len % 128 == 0)
            {
                len1 = len / 128;
            }
            else
            {
                len1 = len / 128 + 1;
            }
            List<byte> tempbytes = new List<byte>();
            for (int i = 0; i < len1; i++)
            {
                if (len >= 128)
                {
                    blockLen = 128;
                }
                else
                {
                    blockLen = len;
                }
                byte[] oText = new byte[blockLen];
                Array.Copy(dataBytes, i * 128, oText, 0, blockLen);
                BigInteger biText = new BigInteger(oText);
                BigInteger biEnText = biText.modPow(KeyNum, nNum);
                byte[] testbyte= biEnText.getBytes();
                string str = Encoding.UTF8.GetString(testbyte);
                tempbytes.AddRange(testbyte);
                len -= blockLen;
            }
            return System.Text.Encoding.UTF8.GetString(tempbytes.ToArray());
        }

我调用的方法是:
private void DecryptByPublicKeyTest()
{
//key
byte[] key = Encoding.UTF8.GetBytes("12345");
//用私钥加密key
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] desc = rsa.Encrypt(key, false);
string getsource = Encoding.UTF8.GetString(rsa.Decrypt(desc, false));
RSAParameters para = rsa.ExportParameters(false);

string gets = DecryptByPublicKey(desc, para.Modulus, para.Exponent);
}

但是解密出来的跟原来的“12345”不一样。
...全文
6536 36 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
gbdcn 2012-10-14
  • 打赏
  • 举报
回复
35楼:
web系统:license.dat 它是授权密文
web中有公钥值E N 如KeyUtil.StringTokey("algorithm:RSA;format:X.509;encoded:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChlTqQxO+NE+QScBSRn0GsLU4JW+MI4+9r4/FEPkeDNS9cAkhl8pKI0KA9oyOuJzB1xFs3AY0ZBzzO7UfDIZoIA8ZVfrNLRwRpa5Kd50qIq+H8fvqyc6WtGk9vl+phjE0rXioM/lWzo8d7Or3J6wbezhSISUA5Qkb6+I99p3pubQIDAQAB",new BouncyCastleProvider())
ShinyKang 2011-04-20
  • 打赏
  • 举报
回复
34楼,你公司做了一个web系统,要把它卖给客户,但有授权时间,你必须把 授权时间写入 加密的授权文件中,然后 在客户运行系统时来进行比较,比较的时候就要解密出授权文件中的时间,但私钥不能给客户,所以只能实现私钥加密公钥解密。
没用?你觉得有用不?
popozhu 2011-01-13
  • 打赏
  • 举报
回复

私钥加密,公钥解密,这个做法本身不符合密码学的安全性要求,在实践中没这么用的吧。。。


理解好公钥加密体制

我举两个例子。
1、公钥加密体制用于保密性时,就是公钥加密,私钥解密。 因为公钥是可以公开了, 那么任何人都可以使用公钥对信息进行加密,但是只有持有私钥的人才能正确解密。这样就保证了信息的保密性,因为只有私钥持有者才能正确解密。

2、公钥加密体制用于认证性时,比如数字签名,即私钥持有者对信息进行签名,验证者可以根据公开的公钥进行验证签名是否正确和有效,即实现了认证性,以及不可抵赖性。


hyfbeetle 2010-02-07
  • 打赏
  • 举报
回复
正苦着找呀。到底dotnet能否实现私钥加密、公钥解密?
liyoubaidu 2009-07-29
  • 打赏
  • 举报
回复
RSA算法是不可能实现私钥加密,公钥解密的(至少目前的数学家做不到)。

RSA算法的意图是:公钥加密,私钥解密,公钥不可解密。从而保护信息安全。
稍微有点无敌 2009-07-28
  • 打赏
  • 举报
回复
to raineo:不要误人哦!
.net 的RSACryptoServiceProvider 真实现公钥加密,私钥解密,所以你的代码是有问题的

如果要实现实现私钥加密,公钥解密,可以使用RSACryptoServiceProvider 的签名和验证功能,其实这个不是很实际意义上的RSA加密解密
R_hgt 2009-07-09
  • 打赏
  • 举报
回复
mark 关注
greenery 2009-07-08
  • 打赏
  • 举报
回复
哇,楼上不要误导人啊

//导入私匙 来加密
RSA.ImportParameters(TempRSA.ExportParameters(false));
byte[] EnCode = RSA.Encrypt(Code, false);
这里你导出的是公钥啊。
牧之~ 2009-06-02
  • 打赏
  • 举报
回复
公钥必须和那个私钥配对的才可以.
zenowolf 2009-06-02
  • 打赏
  • 举报
回复

byte[] Code = System.Text.Encoding.UTF8.GetBytes("1232324");

RSACryptoServiceProvider TempRSA = new RSACryptoServiceProvider();
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

//导入私匙 来加密
RSA.ImportParameters(TempRSA.ExportParameters(false));
byte[] EnCode = RSA.Encrypt(Code, false);

//导入公匙来解密
RSA.ImportParameters(TempRSA.ExportParameters(true));
byte[] DeCode = RSA.Decrypt(EnCode, false);

string temps = System.Text.Encoding.UTF8.GetString(DeCode);
zenowolf 2009-06-02
  • 打赏
  • 举报
回复

RSACryptoServiceProvider TempRSA = new RSACryptoServiceProvider();
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

//导入私匙 来加密
RSA.ImportParameters(TempRSA.ExportParameters(false));
byte[] EnCode = RSA.Encrypt(Code, false);

//导入公匙来解密
RSA.ImportParameters(TempRSA.ExportParameters(true));
byte[] DeCode = RSA.Decrypt(EnCode, false);

string temps = System.Text.Encoding.UTF8.GetString(DeCode);


一般私匙是保存在密匙容器里
junyi2003 2009-06-02
  • 打赏
  • 举报
回复

AsymmetricKeyParameter 是第三方的类,不是.net类库的。这个第三方是仿照Java写的,基本实现了ASN.1协议的。
.net的非对称加密很好没有实现ASN.1,封装的也不好。具体前人已经写过一些对比文章了,我也不罗嗦了。
第三方类库地址 http://www.bouncycastle.org/csharp
参考文章 http://www.cnblogs.com/jobs/archive/2006/09/22/512297.html
Ken_Xie 2009-06-01
  • 打赏
  • 举报
回复
楼上的例子还是用公钥加密呀,楼主说的是要用私钥加密吧?
iloveppmm 2009-06-01
  • 打赏
  • 举报
回复
u
junyi2003 2009-06-01
  • 打赏
  • 举报
回复
总算在垃圾里面找到了以前的代码
一定要用.net 实现的话,推荐 http://www.bouncycastle.org/
我是用VS2005 在 2007年实现的,版本可能老了点。希望对你有帮助

using System;
using System.IO;
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Agreement;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509;

namespace RSAKeyTest
{
public class KeyRSA
{
public static void Main(string[] args)
{

try
{
byte[] b1 = System.Convert.FromBase64String("AAAAgK3VW9wGpQybzYMQaJ7GX3lSHr9+mvNDmx4883Sv3L8Wa/s+GAFjXru6yvX2hHPgY9HX3rpNhfVo7PC9dY1gGyAytMuYGLt6rRAptJqzygZL3GeL//abfyYgnRUFSDmEznhnM1pQfSko9TH9XKKCpNYeYSDTFpJw19R/65tR7obG2Hlc5XdhwtWe24n9jl5AsP3Klp/FY/z0sq9w9Boz6r4=");
byte[] b2 = new byte[128];
for (int i = 0; i < 128; i++)
{
b2[i] = b1[i + 4];
Console.WriteLine("byte[" + i + "]:" + b2[i]);
}

byte[] b3 = new byte[16];
for (int i = 0; i < 16; i++)
{
b3[i] = b2[i];

}

//Console.WriteLine("Plan decrynt text:" + new String(b2));

byte[] encodedata = null;
encodedata = System.Convert.FromBase64String("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDF+vv+Mm+fweJBXM0Is2DDRczTmipTQmxFDnohGMggOU+gFFgeZ8JSx4lMHU+MCw96kQqFaII6UAA11Jc4ZP26dTkvdulX09y3HglTNw4eVidV/h4aA6Anx3bpPU9NjgHhG1oEOXiYexmmOlhrvTU3ToSGpl5z533hGErNqSBP9QIDAQAB");
AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(encodedata);

byte[] decSessionKey = decrypt(pubKey, b2);

int keyLen = 128/8;
byte[] sessionKey = new byte[keyLen];
int decSessionKeyLen = decSessionKey.Length;
for (int i = 0; i < keyLen; i++)
{
sessionKey[i] = decSessionKey[decSessionKeyLen - keyLen + i];
}
string base64SessionKey = Convert.ToBase64String(sessionKey);
Console.WriteLine("out2:" + base64SessionKey);
// Console.WriteLine("pubkey:" + new sun.misc.BASE64Encoder().encode( publicKey.getEncoded()));
// byte[] result = KeyRSA.decrypt2(publicKey,b2);
//Console.WriteLine("Decrytpt text(base64):" + new sun.misc.BASE64Encoder().encode(result));
//Console.WriteLine("out2:" + new sun.misc.BASE64Encoder().encode(decrypt(publicKey,b2)));

//pubKeySpec.
//Key pubkey = new RSAPublicKey();
}
catch
{

}

}

public static byte[] decrypt(AsymmetricKeyParameter key, byte[] raw)
{
try {
IBufferedCipher c = CipherUtilities.GetCipher("RSA");
c.Init(false, key);
int blockSize = c.GetBlockSize();
c.ProcessBytes(raw);

byte[] outbytes = c.DoFinal();
return outbytes;
} catch (Exception e) {
throw (e);
}
}

}

}
Ken_Xie 2009-06-01
  • 打赏
  • 举报
回复
当然不一样,JAVA产生的私钥没办法在.net里面转换为AsymmetricKeyParameter,公钥确是可以的,你的例子上就可以看出来。同样的,通过JAVA产生的私钥也没办法在转换为System.Security.Cryptography里的RSAParameters对象,公钥却可以通过将modulus和exponent都翻转来获取System.Security.Cryptography里的RSAParameters对象,MSDN就有讲到。不要想当然了,如果可以转换,还望多加指教,贴个例子瞧瞧。我自己做了测试,没有成功,公钥是可以的,转换后的公钥可以验证加密的数据,我的理解RSA的公钥只要modulus,exponent,私钥却需要更多的信息内容,例如D,N等。上面的回复错别字太多,请见谅,我没办法修改,只能重新回复一下了。
Ken_Xie 2009-06-01
  • 打赏
  • 举报
回复
当然不一样,JAVA产生的私钥没办法在.net里面AsymmetricKeyParameter,公钥确是可以的。同意的,通过JAVA产生的私钥也没办法在获得RSAParameters,公钥却可以通过将modulus和exponent都翻转来获取。
junyi2003 2009-06-01
  • 打赏
  • 举报
回复
有区别吗? 非对称加密,即可以公钥加密也可以私钥加密啊。解密的时候公钥加的密就用私钥解,私钥加的就用公钥解。
我前面的定义里面已经说了。
上面只是一个例子,看得懂的人都知道是可以互换的。这个我做的是公钥解密的例子,关于这个解密的函数,Key是个参数项。也就是说可能是私钥可能是公钥。
rightyeah 2009-05-31
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 Profiteerchen 的回复:]
5)UI工具运行,首先读取license签名内容,Base64解码,用公钥解密,把解密的内容和系统的第一个硬盘序列号比对,一致则通过,否则进入注册页面,等待注册。
[/Quote]
这就没错了,RSACryptoServiceProvider.VerirySign需要3个参数,一是明文,用硬盘序列号,2是签名内容,用base64解码后的字串,3是加密方法,选择一个合适的就可以了
rightyeah 2009-05-31
  • 打赏
  • 举报
回复
看看msdn的demo
http://msdn.microsoft.com/zh-cn/library/9tsc5d0z.aspx
加载更多回复(16)

111,108

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧