8 个解决方案
#1
理论上n和d就足够了:
m = pow(c,d) mod n
其中c为秘文,m为明文。pow为计算c的d次方。
但是,DotNet的实现可能用了一些快速算法(比如中国剩余定理),因此如果你要用RSACryptoServiceProvider的话,那些P,Q等也需要。
m = pow(c,d) mod n
其中c为秘文,m为明文。pow为计算c的d次方。
但是,DotNet的实现可能用了一些快速算法(比如中国剩余定理),因此如果你要用RSACryptoServiceProvider的话,那些P,Q等也需要。
#2
能给个详细一点的算法么,我弄的好像不是很对哎,谢谢啦,
#3
如果pq那些都有的话怎么初始化啊,网上看了好像没明白怎么用这些值初始化
#4
求指导啊 。。。。。。。。。。。。。。。。。
#5
注意BigInteger在DotNet4或以上才正式支持,需要添加System.Numerics引用。
如果你已经有了PQ等等,可以直接用RSAParameters导入:
RSAParameters par = new RSAParameters();
par.Modulus = n;
par.D = d;
par.Exponent = e;
par.P = ...;
...
using System;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Numerics; // <--
using System.Security.Cryptography;
class Program
{
static string key =
@"<RSAKeyValue>
<Modulus>qjWim96tKp7fMgYtAKZRnLW1dOhbUAsWnzD1MMgtXC9WQYa72/riPTEUM+woW0lMHQKwKUKNVmwZ0TuSAzXAuX8frWU9g/iTL/wxqkql8fCzuGA21+4bvsu3RfuRM4mHY2A9hwLw6pugvz8sogao0x+j/HRUlnpwD7z/CQenats=</Modulus>
<Exponent>AQAB</Exponent>
<P>1xrSggP33Z3zi2pR6y86xCtJxZoDSCm382f0BZRgBv9FXPb2NU+jhS2hstIEED69Xr2t2jSwsXOlnw9wS/zgEw==</P>
<Q>ypHBK9N6Z9O6n83saF+zWsSG9ZPgKwWAWbLnEhEQzbcDCHivz1OZInBqPb2wieAh1uzFywtXpdy7nWoWux9zGQ==</Q>
<DP>hdTLWlcrtTfb2kbZFvF4p6qjKI1NM225ZHit63bIVDIortF8l+invWmJrF9cZdsTKUnsS9HyiUWBqzgIz05S/w==</DP>
<DQ>ZAv4zBx2qDD6S1L5H9OkUYAe58tRO+5LpgGl/lZPZkqtRNHWgx9W0puS3UuClZYNIIlwZwgDEfgi8WwkLecqgQ==</DQ>
<InverseQ>DmS5UXVYYSRcIrgyMf8ZX/4fidDPeIEz834gmjx9VuPQhgL0wXbXog7rpsAQ9+3m1/BvoXyB1okg76BEdg52RQ==</InverseQ>
<D>c2zZ7+/q6LtCSq8rd4RSVf5Xpocn3TkXxy6xJ7qoIBqt2NPgs4YIREzzEV714ynqpsW65tAN/uxh+aT3GJwsK8POGUNowVoDwAASFOhEQD/RJVaiowB1Q6O6uTYFHE34e95XHVv3G58c8bG+87cmOjWSFfewTc993Z2kbAuoR5E=</D>
</RSAKeyValue>";
static void Main(string[] args)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(key);
byte[] encrypted = rsa.Encrypt(Encoding.UTF8.GetBytes("hello"), false);
byte[] decrypted = MyRSADecrypted(encrypted, false);
string str = Encoding.UTF8.GetString(decrypted); //"hello"
}
private static BigInteger FromBytes(byte[] beBytes)
{
// 1、BigInteger的构造函数接受byte[]的格式是“低位在前(Litter Endian)”。所以以下两行是等价的:
// new BigInteger(new byte[]{1, 2, 3, 4})
// new BitInteger(new byte[]{1, 2, 3, 4, 0, 0, 0})
// 2、BigInteger支持负数,如果byte[]的最高二进制位非零,则表示为负数,比如new byte[]{1,2,3, 0x80}就是负数。
// 而RSA中的参数都是正整数,因此,Concat(0)用来保证正整数。
// 3、如果输入的byte[]的格式是“高位在前(Big Endian)”,那么要先用Reverse翻转一次。
return new BigInteger(beBytes.Reverse().Concat(new byte[] { 0 }).ToArray());
}
/// <summary>
/// 只用n和d来进行RSA解密
/// </summary>
private static byte[] MyRSADecrypted(byte[] encrypted, bool fOAEP)
{
XElement keyXml = XElement.Parse(key);
byte[] Modulus = Convert.FromBase64String((string)keyXml.Element("Modulus"));
byte[] D = Convert.FromBase64String((string)keyXml.Element("D"));
BigInteger c = FromBytes(encrypted);
BigInteger n = FromBytes(Modulus);
BigInteger d = FromBytes(D);
BigInteger m = BigInteger.ModPow(c, d, n); // 见公式
var bytes = m.ToByteArray().Reverse();
if (fOAEP) throw new NotImplementedException("TODO");
else bytes = bytes.SkipWhile(b => b != 0).Skip(1); // 去掉PKCS#1 V1.5铺垫,省略检验。
return bytes.ToArray();
}
}
如果你已经有了PQ等等,可以直接用RSAParameters导入:
RSAParameters par = new RSAParameters();
par.Modulus = n;
par.D = d;
par.Exponent = e;
par.P = ...;
...
#6
非常非常感谢了,还是有一个问题,我添加了biginteger的引用了,但是总是提示biginteger并不包含modpow的定义,啥情况啊,我是.net 4.0的
#7
楼上的问题找到了,我之前用的另一个大数类,有点问题,换了vs的好了,话说那个解密的里面bool fOAEP是啥的标记
#8
bool fOAEP控制如何凑齐数据(输入数据要被加到128个字节长)。
如果是真,则用OAEP padding,
如果是假,则用PKCS#1 v1.5 padding。
其中PKCS#1 v1.5比较简单,它的形式如下:
0T PPPPPPPPPPPP 0DDDDDDDDDDDDDDDDDDDDD
总共128个字节,其中
第一个0是先导零,要来保证正整数;
T是凑齐方法,可以是0,1,或者2;
P就是填充数据;
第二个0是分隔符;
D就是原始数据。
而当
T=0: 所有的P都必须为0
T=1: 所有的P都必须为255
T=2: P是不为零的随机数。
MyRSADecrypted(有错别字,改为MyRSADecrypt)目前只支持PKCS#1 v1.5填充。所以当fOAEP==true的时候,它将抛出‘尚未实现’异常。
如果是真,则用OAEP padding,
如果是假,则用PKCS#1 v1.5 padding。
其中PKCS#1 v1.5比较简单,它的形式如下:
0T PPPPPPPPPPPP 0DDDDDDDDDDDDDDDDDDDDD
总共128个字节,其中
第一个0是先导零,要来保证正整数;
T是凑齐方法,可以是0,1,或者2;
P就是填充数据;
第二个0是分隔符;
D就是原始数据。
而当
T=0: 所有的P都必须为0
T=1: 所有的P都必须为255
T=2: P是不为零的随机数。
MyRSADecrypted(有错别字,改为MyRSADecrypt)目前只支持PKCS#1 v1.5填充。所以当fOAEP==true的时候,它将抛出‘尚未实现’异常。
#1
理论上n和d就足够了:
m = pow(c,d) mod n
其中c为秘文,m为明文。pow为计算c的d次方。
但是,DotNet的实现可能用了一些快速算法(比如中国剩余定理),因此如果你要用RSACryptoServiceProvider的话,那些P,Q等也需要。
m = pow(c,d) mod n
其中c为秘文,m为明文。pow为计算c的d次方。
但是,DotNet的实现可能用了一些快速算法(比如中国剩余定理),因此如果你要用RSACryptoServiceProvider的话,那些P,Q等也需要。
#2
能给个详细一点的算法么,我弄的好像不是很对哎,谢谢啦,
#3
如果pq那些都有的话怎么初始化啊,网上看了好像没明白怎么用这些值初始化
#4
求指导啊 。。。。。。。。。。。。。。。。。
#5
注意BigInteger在DotNet4或以上才正式支持,需要添加System.Numerics引用。
如果你已经有了PQ等等,可以直接用RSAParameters导入:
RSAParameters par = new RSAParameters();
par.Modulus = n;
par.D = d;
par.Exponent = e;
par.P = ...;
...
using System;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Numerics; // <--
using System.Security.Cryptography;
class Program
{
static string key =
@"<RSAKeyValue>
<Modulus>qjWim96tKp7fMgYtAKZRnLW1dOhbUAsWnzD1MMgtXC9WQYa72/riPTEUM+woW0lMHQKwKUKNVmwZ0TuSAzXAuX8frWU9g/iTL/wxqkql8fCzuGA21+4bvsu3RfuRM4mHY2A9hwLw6pugvz8sogao0x+j/HRUlnpwD7z/CQenats=</Modulus>
<Exponent>AQAB</Exponent>
<P>1xrSggP33Z3zi2pR6y86xCtJxZoDSCm382f0BZRgBv9FXPb2NU+jhS2hstIEED69Xr2t2jSwsXOlnw9wS/zgEw==</P>
<Q>ypHBK9N6Z9O6n83saF+zWsSG9ZPgKwWAWbLnEhEQzbcDCHivz1OZInBqPb2wieAh1uzFywtXpdy7nWoWux9zGQ==</Q>
<DP>hdTLWlcrtTfb2kbZFvF4p6qjKI1NM225ZHit63bIVDIortF8l+invWmJrF9cZdsTKUnsS9HyiUWBqzgIz05S/w==</DP>
<DQ>ZAv4zBx2qDD6S1L5H9OkUYAe58tRO+5LpgGl/lZPZkqtRNHWgx9W0puS3UuClZYNIIlwZwgDEfgi8WwkLecqgQ==</DQ>
<InverseQ>DmS5UXVYYSRcIrgyMf8ZX/4fidDPeIEz834gmjx9VuPQhgL0wXbXog7rpsAQ9+3m1/BvoXyB1okg76BEdg52RQ==</InverseQ>
<D>c2zZ7+/q6LtCSq8rd4RSVf5Xpocn3TkXxy6xJ7qoIBqt2NPgs4YIREzzEV714ynqpsW65tAN/uxh+aT3GJwsK8POGUNowVoDwAASFOhEQD/RJVaiowB1Q6O6uTYFHE34e95XHVv3G58c8bG+87cmOjWSFfewTc993Z2kbAuoR5E=</D>
</RSAKeyValue>";
static void Main(string[] args)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(key);
byte[] encrypted = rsa.Encrypt(Encoding.UTF8.GetBytes("hello"), false);
byte[] decrypted = MyRSADecrypted(encrypted, false);
string str = Encoding.UTF8.GetString(decrypted); //"hello"
}
private static BigInteger FromBytes(byte[] beBytes)
{
// 1、BigInteger的构造函数接受byte[]的格式是“低位在前(Litter Endian)”。所以以下两行是等价的:
// new BigInteger(new byte[]{1, 2, 3, 4})
// new BitInteger(new byte[]{1, 2, 3, 4, 0, 0, 0})
// 2、BigInteger支持负数,如果byte[]的最高二进制位非零,则表示为负数,比如new byte[]{1,2,3, 0x80}就是负数。
// 而RSA中的参数都是正整数,因此,Concat(0)用来保证正整数。
// 3、如果输入的byte[]的格式是“高位在前(Big Endian)”,那么要先用Reverse翻转一次。
return new BigInteger(beBytes.Reverse().Concat(new byte[] { 0 }).ToArray());
}
/// <summary>
/// 只用n和d来进行RSA解密
/// </summary>
private static byte[] MyRSADecrypted(byte[] encrypted, bool fOAEP)
{
XElement keyXml = XElement.Parse(key);
byte[] Modulus = Convert.FromBase64String((string)keyXml.Element("Modulus"));
byte[] D = Convert.FromBase64String((string)keyXml.Element("D"));
BigInteger c = FromBytes(encrypted);
BigInteger n = FromBytes(Modulus);
BigInteger d = FromBytes(D);
BigInteger m = BigInteger.ModPow(c, d, n); // 见公式
var bytes = m.ToByteArray().Reverse();
if (fOAEP) throw new NotImplementedException("TODO");
else bytes = bytes.SkipWhile(b => b != 0).Skip(1); // 去掉PKCS#1 V1.5铺垫,省略检验。
return bytes.ToArray();
}
}
如果你已经有了PQ等等,可以直接用RSAParameters导入:
RSAParameters par = new RSAParameters();
par.Modulus = n;
par.D = d;
par.Exponent = e;
par.P = ...;
...
#6
非常非常感谢了,还是有一个问题,我添加了biginteger的引用了,但是总是提示biginteger并不包含modpow的定义,啥情况啊,我是.net 4.0的
#7
楼上的问题找到了,我之前用的另一个大数类,有点问题,换了vs的好了,话说那个解密的里面bool fOAEP是啥的标记
#8
bool fOAEP控制如何凑齐数据(输入数据要被加到128个字节长)。
如果是真,则用OAEP padding,
如果是假,则用PKCS#1 v1.5 padding。
其中PKCS#1 v1.5比较简单,它的形式如下:
0T PPPPPPPPPPPP 0DDDDDDDDDDDDDDDDDDDDD
总共128个字节,其中
第一个0是先导零,要来保证正整数;
T是凑齐方法,可以是0,1,或者2;
P就是填充数据;
第二个0是分隔符;
D就是原始数据。
而当
T=0: 所有的P都必须为0
T=1: 所有的P都必须为255
T=2: P是不为零的随机数。
MyRSADecrypted(有错别字,改为MyRSADecrypt)目前只支持PKCS#1 v1.5填充。所以当fOAEP==true的时候,它将抛出‘尚未实现’异常。
如果是真,则用OAEP padding,
如果是假,则用PKCS#1 v1.5 padding。
其中PKCS#1 v1.5比较简单,它的形式如下:
0T PPPPPPPPPPPP 0DDDDDDDDDDDDDDDDDDDDD
总共128个字节,其中
第一个0是先导零,要来保证正整数;
T是凑齐方法,可以是0,1,或者2;
P就是填充数据;
第二个0是分隔符;
D就是原始数据。
而当
T=0: 所有的P都必须为0
T=1: 所有的P都必须为255
T=2: P是不为零的随机数。
MyRSADecrypted(有错别字,改为MyRSADecrypt)目前只支持PKCS#1 v1.5填充。所以当fOAEP==true的时候,它将抛出‘尚未实现’异常。