题
目前,我正在试图实现一个类来使用RSACrytoServiceProveider类我的应用程序的实例之间处理安全通信。 第一个问题:这是一个好主意,实行单一的类来处理发送/ reciever角色或我应该角色拆分成单独的类?这是我迄今所做的:
using System;
using System.Text;
using System.Security.Cryptography;
namespace Agnus.Cipher
{
public class RSA
{
private byte[] plaintextBytes;
private byte[] ciphertextBytes;
private RSACryptoServiceProvider rSAProviderThis;
private RSACryptoServiceProvider rSAProviderOther;
public string PublicKey
{
get { return rSAProviderThis.ToXmlString(false); }
}
public RSA()
{
rSAProviderThis = new RSACryptoServiceProvider { PersistKeyInCsp = true };
plaintextBytes = Encoding.Unicode.GetBytes(PublicKey);
}
public void InitializeRSAProviderOther(string parameters)
{
rSAProviderOther.FromXmlString(parameters);
}
public byte[] Encrypt()
{
return rSAProviderThis.Encrypt(plaintextBytes, true);
}
public byte[] Decrypt()
{
return rSAProviderThis.Decrypt(ciphertextBytes, true);
}
public byte[] Sign()
{
using (SHA1Managed SHA1 = new SHA1Managed())
{
byte[] hash = SHA1.ComputeHash(ciphertextBytes);
byte[] signature = rSAProviderThis.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
return signature;
}
}
public void Verify()
{
throw new NotImplementedException();
}
}
}
第二个问题:如何发送和接收数据被馈送到类?我在该字段中的绿色的喇叭,指针将不胜感激。
解决方案
我想使加密/符号/解密/验证方法采取的数据参数,而不是具有用于他们的成员变量。有成员变量的关键和供应商似乎还行,虽然。基本上我期望使用相同的键多次但不相同的数据。
我也想使它不可变的 - 使只读所有的变量,以你需要的而不是一个单独的初始化方法在构造函数中提供的所有参数
除此之外,似乎好为您的需要一个简单的API中,虽然包的功能,是的。
其他提示
我已经做了一些调整,这里是实现的样子:
using System;
using System.Security.Cryptography;
namespace Agnus.Cipher
{
public class RSA : IDisposable
{
private RSACryptoServiceProvider rSAProviderThis;
private RSACryptoServiceProvider rSAProviderOther = null;
public string PublicKey
{
get { return rSAProviderThis.ToXmlString(false); }
}
public RSA()
{
rSAProviderThis = new RSACryptoServiceProvider { PersistKeyInCsp = true };
}
public void InitializeRSAProviderOther(string parameters)
{
rSAProviderOther.FromXmlString(parameters);
}
public byte[] Encrypt(byte[] plaintextBytes)
{
return rSAProviderThis.Encrypt(plaintextBytes, true);
}
public string Decrypt(byte[] ciphertextBytes)
{
try
{
return Convert.ToBase64String( rSAProviderThis.Decrypt(ciphertextBytes, true));
}
catch (CryptographicException ex)
{
Console.WriteLine("Unable to decrypt: " + ex.Message + " " + ex.StackTrace);
}
finally
{
this.Dispose();
}
return string.Empty;
}
public string SignData(byte[] ciphertextBytes)
{
string signature = GenerateSignature(ciphertextBytes, rSAProviderThis);
return signature;
}
private string GenerateSignature(byte[] ciphertextBytes, RSACryptoServiceProvider provider)
{
using (SHA1Managed SHA1 = new SHA1Managed())
{
byte[] hash = SHA1.ComputeHash(ciphertextBytes);
string signature = Convert.ToBase64String(provider.SignHash(hash, CryptoConfig.MapNameToOID("SHA1")));
return signature;
}
}
public string VerifySignature(byte[] ciphertextBytes, string parameters, string signatureToVerify)
{
InitializeRSAProviderOther(parameters);
string actualSignature = GenerateSignature(ciphertextBytes, rSAProviderOther);
if (actualSignature.Equals(signatureToVerify))
{
//verification successful
string decryptedData = this.Decrypt(ciphertextBytes);
return decryptedData;
//decryptedData is a symmetric key
}
else
{
//verification unsuccessful
//end session
}
return string.Empty;
}
#region IDisposable Members
public void Dispose()
{
if (rSAProviderOther != null)
{
rSAProviderOther.Clear();
}
rSAProviderThis.Clear();
GC.SuppressFinalize(this);
}
#endregion
}
}
你们还没有所述通信将如何被建立(我在想插座)任何东西。请赐教。
我不知道这是否剪断的代码,可以帮助你,我已经写了这个代码能够地下室和与不同crypting algortims私有/公共密钥对解密并没有数据加密长度的问题,事实上RSA在.NET实现挨磨片在尝试管理的数据超过250(或多或少,对不起,我不记得)字节。
我只是剪切和粘贴方法只需要,我也板缺XML文档的原因是不是英文的,如果你发现这个有用让我知道,我可以张贴的所有源。我再说一遍,我不测试这个剪切和粘贴的版本,但我用的完整版本这个类是没有什么不同。
BTW:这是在VB,但如果你只需要在它潜伏我认为这是不够的;)
Namespace Crypto
Public Class RSACry
Shared Sub New()
End Sub
Public Enum Algorithms
DES
TDES
RC2
RDAEL
End Enum
Public Shared Function Encrypt(ByVal xmlkeystring As String, ByVal typo As Algorithms, ByVal datatoencrypt As String) As String
Dim rsaer As RSA = Crypto.RSACry.ReadKeyString(xmlkeystring)
Dim result() As Byte = Crypto.RSACry.EncryptIt(rsaer, typo, datatoencrypt)
Return System.Convert.ToBase64String(result)
End Function
Public Shared Function Decrypt(ByVal xmlkeystring As String, ByVal typo As Algorithms, ByVal datatodecrypt As String) As String
Dim rsaer As RSA = Crypto.RSACry.ReadKeyString(xmlkeystring)
Dim result() As Byte = Crypto.RSACry.DecryptIt(rsaer, typo, datatodecrypt)
Return System.Text.Encoding.UTF8.GetString(result)
End Function
Friend Shared Function EncryptIt(ByRef rsaer As RSA, ByVal typo As Algorithms, ByVal datatoencrypt As String) As Byte()
Dim result() As Byte = Nothing
Try
Dim plainbytes() As Byte = System.Text.Encoding.UTF8.GetBytes(datatoencrypt)
Dim sa As SymmetricAlgorithm = SymmetricAlgorithm.Create(Crypto.RSACry.GetAlgorithmName(typo))
Dim ct As ICryptoTransform = sa.CreateEncryptor()
Dim encrypt() As Byte = ct.TransformFinalBlock(plainbytes, 0, plainbytes.Length)
Dim fmt As RSAPKCS1KeyExchangeFormatter = New RSAPKCS1KeyExchangeFormatter(rsaer)
Dim keyex() As Byte = fmt.CreateKeyExchange(sa.Key)
--return the key exchange, the IV (public) and encrypted data
result = New Byte(keyex.Length + sa.IV.Length + encrypt.Length) {}
Buffer.BlockCopy(keyex, 0, result, 0, keyex.Length)
Buffer.BlockCopy(sa.IV, 0, result, keyex.Length, sa.IV.Length)
Buffer.BlockCopy(encrypt, 0, result, keyex.Length + sa.IV.Length, encrypt.Length)
Catch ex As Exception
Throw New CryptographicException("Unable to crypt: " + ex.Message)
End Try
Return result
End Function
Friend Shared Function DecryptIt(ByRef rsaer As RSA, ByVal typo As Algorithms, ByVal datatodecrypt As String) As Byte()
Dim result() As Byte = Nothing
Try
Dim encrbytes() As Byte = System.Convert.FromBase64String(datatodecrypt)
Dim sa As SymmetricAlgorithm = SymmetricAlgorithm.Create(Crypto.RSACry.GetAlgorithmName(typo))
Dim keyex() As Byte = New Byte((rsaer.KeySize >> 3) - 1) {}
Buffer.BlockCopy(encrbytes, 0, keyex, 0, keyex.Length)
Dim def As RSAPKCS1KeyExchangeDeformatter = New RSAPKCS1KeyExchangeDeformatter(rsaer)
Dim key() As Byte = def.DecryptKeyExchange(keyex)
Dim iv() As Byte = New Byte((sa.IV.Length - 1)) {}
Buffer.BlockCopy(encrbytes, keyex.Length, iv, 0, iv.Length)
Dim ct As ICryptoTransform = sa.CreateDecryptor(key, iv)
result = ct.TransformFinalBlock(encrbytes, keyex.Length + iv.Length, (encrbytes.Length - 1) - (keyex.Length + iv.Length))
Catch ex As Exception
Throw New CryptographicException("Unable to decrypt: " + ex.Message)
End Try
Return result
End Function
Friend Shared Function GetAlgorithmName(ByVal typo As Algorithms) As String
Dim algtype As String = String.Empty
Select Case typo
Case Algorithms.DES
Return "DES"
Exit Select
Case Algorithms.RC2
Return "RC2"
Exit Select
Case Algorithms.RDAEL
Return "Rijndael"
Exit Select
Case Algorithms.TDES
Return "TripleDES"
Exit Select
Case Else
Return "Rijndael"
Exit Select
End Select
Return algtype
End Function
Friend Shared Function ReadKeyString(ByVal xmlkeystring As String) As RSA
Dim rsaer As RSA = Nothing
Try
If (String.IsNullOrEmpty(xmlkeystring)) Then Throw New Exception("Key is not specified")
rsaer = RSA.Create()
rsaer.FromXmlString(xmlkeystring)
Catch ex As Exception
Throw New CryptographicException("Unable to load key")
End Try
Return rsaer
End Function
End Namespace
@gogole: 其实我不使用插座,这个代码是在单机方式使用钥匙手动bringed。 然而,一旦你有你的地穴机制,你在超过旅程的一半。
下面还有两人失踪方法来创建密钥,如你要求的代码完成。 我希望你发现这是很有帮助
Public Shared Sub CreateKeyPair(ByVal filename As String)
Dim xmlpublic As String = String.Empty
Dim xmlprivate As String = String.Empty
CreateKeyPair(xmlpublic, xmlprivate)
Try
Dim writer As New StreamWriter(filename + ".prv")
writer.Write(xmlprivate)
writer.Flush()
writer.Close()
Catch ex As Exception
Throw New CryptographicException("Unable to write private key file: " + ex.Message)
End Try
Try
Dim writer = New StreamWriter(filename + ".pub")
writer.Write(xmlpublic)
writer.Flush()
writer.Close()
Catch ex As Exception
Throw New CryptographicException("Unable to write public key file: " + ex.Message)
End Try
End Sub
Public Shared Sub CreateKeyPair(ByRef xmlpublic As String, ByRef xmlprivate As String)
Dim rsa As RSA = Nothing
Try
rsa.Create()
Catch ex As Exception
Throw New CryptographicException("Unable to initialize keys: " + ex.Message)
End Try
Try
xmlpublic = rsa.ToXmlString(True)
Catch ex As Exception
Throw New CryptographicException("Unable to generate public key: " + ex.Message)
End Try
Try
xmlprivate = rsa.ToXmlString(False)
Catch ex As Exception
Throw New CryptographicException("Unable to generate private key: " + ex.Message)
End Try
End Sub
不知道多少VB,但试图@Andrea的Celin一个在C#转换有用的代码的
namespace Crypto
{
using System;
using System.Security.Cryptography;
class RSACry
{
public enum Algorithms
{
DES,
TDES,
RC2,
RDAEL
};
public string Encrypt(string xmlkeystring, Algorithms typo, string datatoencrypt)
{
RSA rsaer = RSACry.ReadKeyString(xmlkeystring);
byte[] result = RSACry.EncryptIt(rsaer, typo, datatoencrypt);
return System.Convert.ToBase64String(result);
}
public string Decrypt(string xmlkeystring,Algorithms typo,string datatodecrypt)
{
RSA rsaer = RSACry.ReadKeyString(xmlkeystring);
byte[] result =RSACry.DecryptIt(rsaer, typo, datatodecrypt);
return System.Text.Encoding.UTF8.GetString(result);
}
public static byte[] EncryptIt(RSA rsaer, Algorithms typo, string datatoencrypt)
{
byte[] result = null;
try
{
byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(datatoencrypt);
SymmetricAlgorithm sa = SymmetricAlgorithm.Create(RSACry.GetAlgorithmName(typo));
ICryptoTransform ct = sa.CreateEncryptor();
byte[] encrypt = ct.TransformFinalBlock(plainbytes, 0, plainbytes.Length);
RSAPKCS1KeyExchangeFormatter fmt = new RSAPKCS1KeyExchangeFormatter(rsaer);
byte[] keyex = fmt.CreateKeyExchange(sa.Key);
//--return the key exchange, the IV (public) and encrypted data
result = new byte[keyex.Length + sa.IV.Length + encrypt.Length];
Buffer.BlockCopy(keyex, 0, result, 0, keyex.Length);
Buffer.BlockCopy(sa.IV, 0, result, keyex.Length, sa.IV.Length);
Buffer.BlockCopy(encrypt, 0, result, keyex.Length + sa.IV.Length, encrypt.Length);
}
catch (Exception ex)
{
throw new CryptographicException("Unable to crypt: " + ex.Message);
}
return result;
}
public static byte[] DecryptIt(RSA rsaer, Algorithms typo, string datatodecrypt)
{
byte[] result = null;
try
{
byte[] encrbytes = System.Convert.FromBase64String(datatodecrypt);
SymmetricAlgorithm sa = SymmetricAlgorithm.Create(RSACry.GetAlgorithmName(typo));
byte[] keyex = new byte[(rsaer.KeySize >> 3) - 1];
Buffer.BlockCopy(encrbytes, 0, keyex, 0, keyex.Length);
RSAPKCS1KeyExchangeDeformatter def = new RSAPKCS1KeyExchangeDeformatter(rsaer);
byte[] key = def.DecryptKeyExchange(keyex);
byte[] iv = new byte[sa.IV.Length - 1];
Buffer.BlockCopy(encrbytes, keyex.Length, iv, 0, iv.Length);
ICryptoTransform ct = sa.CreateDecryptor(key, iv);
result = ct.TransformFinalBlock(encrbytes, keyex.Length + iv.Length, (encrbytes.Length - 1) - (keyex.Length + iv.Length));
}
catch (Exception ex)
{
throw new CryptographicException("Unable to decrypt: " + ex.Message);
}
return result;
}
public static string GetAlgorithmName(Algorithms typo)
{
string algtype = String.Empty;
switch(typo)
{
case Algorithms.DES:
algtype = "DES";
break;
case Algorithms.RC2:
algtype = "RC2";
break;
case Algorithms.RDAEL:
algtype = "Rijndael";
break;
case Algorithms.TDES:
algtype = "TripleDES";
break;
default:
algtype = "Rijndael";
break;
}
return algtype;
}
public static RSA ReadKeyString(string xmlkeystring)
{
RSA rsaer = null;
try
{
if (String.IsNullOrEmpty(xmlkeystring))
{ throw new Exception("Key is not specified"); }
rsaer = RSA.Create();
rsaer.FromXmlString(xmlkeystring);
}
catch (Exception ex)
{
throw new CryptographicException("Unable to load key :"+ex.Message);
}
return rsaer;
}
}
}