Rua*_*ien 10 .net c# encryption cryptography rsa
我知道我可能会得到的主要答案是你为什么要这么做?!
不幸的是,尽管我有抗议,但我必须这样做,尽管我知道它没什么意义.
我有.Net编写的函数使用私钥解密,使用公钥加密.我也签署并验证并对我认为这一切的工作方式有一个合理的理解.
我现在被发送一个使用私钥进行RSA加密的值,我应该通过使用公钥解密来获得可用值.
我似乎无法弄清楚如何做到这一点.我是个白痴吗?这是正常的事吗?
发送给我的人告诉我这在PHP中没问题.我还不知道,还没有使用过PHP.我找不到一个库,用我所知的任何主要语言,即C++,Java,C#.我正在使用的服务器使用.Net.
我希望有人可以帮助我.
如果除了乞求他们改变他们正在做的事情之外还有某种合理的解决方案,那将是很棒的.
这是我的方法(根据Iridium指出的我之前的错误更新)但是当我尝试解密该值时,我得到一个例外
"解码OAEP填充时出错."
如果我使用rsa.Decrypt(bytes,false),我会得到一个错误的密钥异常.
public static string DecryptUsingPublic(string dataEncrypted, string publicKey)
{
if (dataEncrypted == null) throw new ArgumentNullException("dataEncrypted");
if (publicKey == null) throw new ArgumentNullException("publicKey");
try
{
RSAParameters _publicKey = LoadRsaPublicKey(publicKey, false);
RSACryptoServiceProvider rsa = InitRSAProvider(_publicKey);
byte[] bytes = Convert.FromBase64String(dataEncrypted);
byte[] decryptedBytes = rsa.Decrypt(bytes, true);
ArrayList arrayList = new ArrayList();
arrayList.AddRange(decryptedBytes);
return Encoding.UTF8.GetString(decryptedBytes);
}
catch
{
return null;
}
}
private static RSAParameters LoadRsaPublicKey(String publicKeyFilePath, Boolean isFile)
{
RSAParameters RSAKeyInfo = new RSAParameters();
byte[] pubkey = ReadFileKey(publicKeyFilePath, "PUBLIC KEY", isFile);
byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
byte[] seq = new byte[15];
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
MemoryStream mem = new MemoryStream(pubkey);
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
byte bt = 0;
ushort twobytes = 0;
try
{
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return RSAKeyInfo;
seq = binr.ReadBytes(15); //read the Sequence OID
if (!CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct
return RSAKeyInfo;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8203)
binr.ReadInt16(); //advance 2 bytes
else
return RSAKeyInfo;
bt = binr.ReadByte();
if (bt != 0x00) //expect null byte next
return RSAKeyInfo;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return RSAKeyInfo;
twobytes = binr.ReadUInt16();
byte lowbyte = 0x00;
byte highbyte = 0x00;
if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
else if (twobytes == 0x8202)
{
highbyte = binr.ReadByte(); //advance 2 bytes
lowbyte = binr.ReadByte();
}
else
return RSAKeyInfo;
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
int modsize = BitConverter.ToInt32(modint, 0);
byte firstbyte = binr.ReadByte();
binr.BaseStream.Seek(-1, SeekOrigin.Current);
if (firstbyte == 0x00)
{ //if first byte (highest order) of modulus is zero, don't include it
binr.ReadByte(); //skip this null byte
modsize -= 1; //reduce modulus buffer size by 1
}
byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
return RSAKeyInfo;
int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
byte[] exponent = binr.ReadBytes(expbytes);
RSAKeyInfo.Modulus = modulus;
RSAKeyInfo.Exponent = exponent;
return RSAKeyInfo;
}
catch (Exception)
{
return RSAKeyInfo;
}
finally { binr.Close(); }
//return RSAparams;
}
private static RSACryptoServiceProvider InitRSAProvider(RSAParameters rsaParam)
{
//
// Initailize the CSP
// Supresses creation of a new key
//
CspParameters csp = new CspParameters();
//csp.KeyContainerName = "RSA Test (OK to Delete)";
const int PROV_RSA_FULL = 1;
csp.ProviderType = PROV_RSA_FULL;
const int AT_KEYEXCHANGE = 1;
// const int AT_SIGNATURE = 2;
csp.KeyNumber = AT_KEYEXCHANGE;
//
// Initialize the Provider
//
RSACryptoServiceProvider rsa =
new RSACryptoServiceProvider(csp);
rsa.PersistKeyInCsp = false;
//
// The moment of truth...
//
rsa.ImportParameters(rsaParam);
return rsa;
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02) //expect integer
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte(); // data size in next byte
else
if (bt == 0x82)
{
highbyte = binr.ReadByte(); // data size in next 2 bytes
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt; // we already have the data size
}
while (binr.ReadByte() == 0x00)
{ //remove high order zeros in data
count -= 1;
}
binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
return count;
}
private static bool CompareBytearrays(byte[] a, byte[] b)
{
if (a.Length != b.Length)
return false;
int i = 0;
foreach (byte c in a)
{
if (c != b[i])
return false;
i++;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
InitRSAProvider和LoadRsaPublicKey之上的两个方法都是从教程中获得的,以允许PEM键作为字符串与.Net一起使用.
Dun*_*art 14
RSA内置于.NET : System.Security.Cryptography.RSA.
使用公钥进行加密并使用私钥进行解密是人们使用非对称算法最常见的事情之一,它允许任何人安全地向您发送信息.
如果您以相反的方式执行此操作:使用私钥加密,并使用公钥解密,则证明该消息是由私钥持有者发送的.但是因为任何人都可能掌握了公钥,人们不会加密整个消息,而只是使用私钥对数据的哈希进行签名.因此RSACryptoServiceProvider有Sign__和Verify__方法做到这一点.
Encrypt/Decrypt如果你的伴侣坚持,还有一些方法.
说到这一点,我发现Microsoft加密类在处理方面有点棘手,在某些方面缺乏,而且更喜欢Bouncy Castle库.
Iri*_*ium 12
看了一些有关RSA加密模式的信息后,看起来PKCS#1 v1.5(你正在使用它,因为你正在调用Decrypt(..., false))
"...可以对长度达k-11个八位字节的消息进行操作(k是RSA模数的八位字节长度)"
(RFC 3447,强调我的).
根据错误消息,表明您的密钥是128字节,这意味着您无法在超过128 - 11 = 117字节的消息上使用PKCS#1 v1.5执行RSA(en | de)加密.
您应该使用对称算法来加密消息正文,并使用RSA仅加密对称加密密钥,而不是使用RSA直接加密消息.只有当您的消息相当短(即密钥大小低于117个字节)时,您才应考虑直接使用RSA加密消息.
我添加了以下内容,假设您的输入是Base64编码,如下面的评论中所示:
public string DecryptUsingPublic(string dataEncryptedBase64, string publicKey)
{
if (dataEncryptedBase64 == null) throw new ArgumentNullException("dataEncryptedBase64");
if (publicKey == null) throw new ArgumentNullException("publicKey");
try
{
RSAParameters _publicKey = LoadRsaPublicKey(publicKey, false);
RSACryptoServiceProvider rsa = InitRSAProvider(_publicKey);
byte[] bytes = Convert.FromBase64String(dataEncryptedBase64);
byte[] decryptedBytes = rsa.Decrypt(bytes, false);
// I assume here that the decrypted data is intended to be a
// human-readable string, and that it was UTF8 encoded.
return Encoding.UTF8.GetString(decryptedBytes);
}
catch
{
return null;
}
}
Run Code Online (Sandbox Code Playgroud)