A have PHP code to sign the message (using phpseclib 2.0):
function sign($plaintext, $key, $password) {
$rsa = new RSA();
$rsa->setPassword($password);
$rsa->loadKey(file_get_contents($key));
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$signature = $rsa->sign(hash('sha256', $plaintext));
return base64_encode($signature);
}
Public and private keys format is PEM. I need to verify this signature with C#. I am trying this code, but it returns false:
public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
{
bool success = false;
using (var rsa = new RSACryptoServiceProvider())
{
var encoder = new UTF8Encoding();
byte[] bytesToVerify = encoder.GetBytes(originalMessage);
byte[] signedBytes = Convert.FromBase64String(signedMessage);
try
{
rsa.ImportParameters(publicKey);
SHA256Managed Hash = new SHA256Managed();
byte[] hashedData = Hash.ComputeHash(bytesToVerify);
success = rsa.VerifyData(hashedData, CryptoConfig.MapNameToOID("SHA256"), signedBytes);
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
return success;
}
Usage:
RSACryptoServiceProvider rsa = PemKeyUtils.PemKeyUtils.GetRSAProviderFromPemFile("public.key");
MessageBox.Show(VerifyData("my message", #"ZpQMPYlMIgME/H0sRYBnyEf/yJ/eBc5bznYZ2nMFn/I6Ts3u8P3x0QgzbUxPnhUgfKhcrEC2UgffyzWzCfwT3Bs+lm6Q89N5bkWK08WKnWaFxr2GQ6+gNyPyUKUgfy851xIHU7EMR6bZt/IndPC+lAAXSxxddPwLelrI8ktgyMVvMUzfCh3AeNCBuY5sSRwkAKH2myPBThJKNjKSZVEb4tO4oiPPWlBuifqmWvbQeMFuKANY0dZNCUFVjlnkaHnwVNzVs1BhNTEML2MKmWvKofafbtcG8J1F+7PapppZwT7OFqhosCSrrzRX49cR4y/7b0syJozmJSebKDpy6FPefA==", rsa.ExportParameters(false)).ToString());
PemKeyUtils class from this answer.
What's wrong? How can I verify signature with C#?
VerifyData() computes the hash itself, so you've ended up hashing the data twice in your C# code. Just provide the data directly to VerifyData() without hashing it yourself.
EDIT: Ok, now I see that you are also hashing it twice on the php side, the first time with SHA1 and the second time with SHA256. Just hash it once, using SHA256, just it like shows in the examples.
function sign($plaintext, $key, $password) {
$rsa = new RSA();
$rsa->setPassword($password);
$rsa->loadKey(file_get_contents($key));
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$rsa->setHash('sha256')
$signature = $rsa->sign($plaintext);
return base64_encode($signature);
}
Related
How to change C# encryption method to the same as swift? I tried below code, but it's converting the string different. I want according to same as swift due to decryption method. I am using 3des. My C# method encrypt/decrypt is working fine.
I want same as C# in Swift.
C#
public static string Encrypt(string PlainText)
{
try
{
if (PlainText.Length > 0)
{
string key = "FIFEDCBA98765432104AABFD";
byte[] PlainTextArray = UTF8Encoding.UTF8.GetBytes(PlainText);
byte[] keyArray = MD5.CreateMd5ByteArray(key);
TripleDESCryptoServiceProvider TripleDes = new TripleDESCryptoServiceProvider();
TripleDes.Key = keyArray;
TripleDes.Mode = CipherMode.ECB;
TripleDes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = TripleDes.CreateEncryptor();
byte[] CipherString = cTransform.TransformFinalBlock(PlainTextArray, 0, PlainTextArray.Length);
TripleDes.Clear();
return Convert.ToBase64String(CipherString, 0, CipherString.Length);
}
else
{
return null;
}
}
catch (Exception ex)
{
throw;
}
}
SWIFT
func tripleDesEncrypt(PlainString: String) -> String{
let keyData = "FIFEDCBA98765432104AABFD"
let PlainStringvar = PlainString
guard let data = PlainStringvar.data(using: .utf8) else {
return ""
}
let cryptData = NSMutableData(length: Int(data.count) + kCCBlockSize3DES)!
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
nil,
data.bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
var base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString//// encodeString(str: base64cryptString)
} else {
print("Error: \(cryptStatus)")
}
return ""
}
Your problem in C# appears to be this line:
byte[] keyArray = MD5.CreateMd5ByteArray(key);
Assuming that function (which is not part of the .NET BCL, so I assume it's something custom that you wrote) creates an MD5 hash of your 3DES key, that's the only difference between your C# and Swift versions.
In Swift, you encrypt the value using a key which is the UTF-8 encoded value of "FIFE...".
In C#, you encrypt the value using a key which is the MD5 hash of the UTF-8 encoded value if "FIFE...".
If you replace that line with the following one:
var keyArray = Encoding.UTF8.GetBytes(key);
then both functions return the same ciphertext for the same plaintext values.
I'm currently working on a class that encrypts large amounts of text with a randomly generated encryption key encrypted by a X509 certificate from a smart card, using a RSACryptoServiceProvider to perform the master key encryption and decryption operations. However, when I have the fOEAP padding option set to true, I have the "Error while decoding OAEP padding" error on decryption every time. I've checked the key size and it is within acceptable limits. And I've gone through breakpoints to make sure that the Base64 string that gets returned from the encryption function is the exact same as the encrypted Base64 string that gets passed back to the decryption function when the file gets loaded again.
The key pair is definitely correct, since it works fine without OAEP. And I've checked the text encoding too.
EDIT: It turns out this could be a smart card specific issue, when I tried decryption with a local X509 certificate the decryption succeeded.
EDIT: This is the decryption code that fails:
string TestString = "Hello World!";
X509Certificate2 cert = DRXEncrypter.GetCertificate("Select a test certificate", "Select a certificate to use for this test from the local store.");
string key = DRXEncrypter.GenerateEncryptionKey(214);
Console.WriteLine("Encryption Key: " + key);
string encrypted = DRXEncrypter.EncryptBody(TestString, key);
Console.WriteLine("Encrypted Body: " + encrypted);
string cryptokey = DRXEncrypter.EncryptWithCert(cert, key);
Console.WriteLine("Encrypted Decryption Key: " + cryptokey);
string decrypted = DRXEncrypter.DecryptBody(encrypted, cryptokey, cert);
Console.WriteLine("Decrypted Body: " + decrypted);
Console.WriteLine("Output String: " + decrypted + ".");
Here is the code from the crypto provider class I've written. I've been stuck on this issue for hours, so it would be great if someone could help me out.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.IO;
namespace CoreDRXEditor
{
public class DRXEncrypter
{
private byte[] Salt = Encoding.ASCII.GetBytes("81PO9j8I1a94j");
private string EncryptionKey;
private const bool UseOAEP = true;
public DRXEncrypter(string EncryptionKey)
{
this.EncryptionKey = EncryptionKey;
}
public static string EncryptBody(string body, string encryptionkey)
{
// Use the plaintext master key to encrypt the body.
DRXEncrypter enc = new DRXEncrypter(encryptionkey);
// Encrypt the body.
return enc.Encrypt(body);
}
public static int GetMaxKeySize(X509Certificate2 cert)
{
RSACryptoServiceProvider csp = cert.PublicKey.Key as RSACryptoServiceProvider;
return csp.KeySize;
}
public static string DecryptBody(string body, string encryptionkey, X509Certificate2 cert)
{
// Decrypt the encrypted encryption key with the certificate.
string DecryptedKey = Convert.ToBase64String(DecryptWithCert(cert, encryptionkey));
// Create a new DRXEncrypter using the decrypted encryption key to decrypt the body.
DRXEncrypter enc = new DRXEncrypter(DecryptedKey);
// Return the decrypted body.
return enc.Decrypt(body);
}
public static string GenerateEncryptionKey(int KeyLength)
{
using (RandomNumberGenerator rng = new RNGCryptoServiceProvider())
{
byte[] CryptoBytes = new byte[KeyLength];
rng.GetBytes(CryptoBytes);
return Convert.ToBase64String(CryptoBytes);
}
}
public static X509Certificate2 GetCertificate(string title, string message)
{
X509Store cstore = new X509Store(StoreLocation.CurrentUser);
cstore.Open(OpenFlags.ReadOnly);
X509CertificateCollection certs = X509Certificate2UI.SelectFromCollection(cstore.Certificates, title, message, X509SelectionFlag.SingleSelection);
if (certs.Count == 1)
{
X509Certificate2 mcert = certs[0] as X509Certificate2;
return mcert;
}
else
{
return null;
}
}
public static string EncryptWithCert(X509Certificate2 cert, string PlainText)
{
RSACryptoServiceProvider csp = cert.PublicKey.Key as RSACryptoServiceProvider;
byte[] PlainBytes = Convert.FromBase64String(PlainText);
// This converts the plain text into a byte array and then encrypts the raw bytes.
byte[] CryptoBytes = csp.Encrypt(PlainBytes, UseOAEP);
// This converts the encrypted bytes into a Base64 string.
string ReturnString = Convert.ToBase64String(CryptoBytes);
return ReturnString;
}
public static byte[] DecryptWithCert(X509Certificate2 cert, string EncryptedText)
{
RSACryptoServiceProvider csp = cert.PrivateKey as RSACryptoServiceProvider;
//CspParameters csps = new CspParameters();
byte[] EncryptedBytes = Convert.FromBase64String(EncryptedText);
// This converts the encrypted, Base64 encoded byte array from EncryptWithCert() to a byte[] and decrypts it.
byte[] CryptoBytes = csp.Decrypt(EncryptedBytes, UseOAEP);
return CryptoBytes;
}
public string Encrypt(string PlainText)
{
RijndaelManaged Algorithm = null;
string Output = null;
try
{
Rfc2898DeriveBytes PrivateKey = new Rfc2898DeriveBytes(this.EncryptionKey, this.Salt);
Algorithm = new RijndaelManaged();
Algorithm.Key = PrivateKey.GetBytes(Algorithm.KeySize / 8);
Algorithm.Padding = PaddingMode.PKCS7;
ICryptoTransform Encryption = Algorithm.CreateEncryptor(Algorithm.Key, Algorithm.IV);
using (MemoryStream msa = new MemoryStream())
{
msa.Write(BitConverter.GetBytes(Algorithm.IV.Length), 0, sizeof(int));
msa.Write(Algorithm.IV, 0, Algorithm.IV.Length);
using (CryptoStream csa = new CryptoStream(msa, Encryption, CryptoStreamMode.Write))
{
using (StreamWriter swa = new StreamWriter(csa))
{
swa.Write(PlainText);
}
}
Output = Convert.ToBase64String(msa.ToArray());
}
}
finally
{
if (Algorithm != null)
{
Algorithm.Clear();
}
}
return Output;
}
public string Decrypt(string EncryptedText)
{
RijndaelManaged Algorithm = null;
string Output = null;
try
{
Rfc2898DeriveBytes PrivateKey = new Rfc2898DeriveBytes(this.EncryptionKey, this.Salt);
byte[] KeyBytes = Convert.FromBase64String(EncryptedText);
using (MemoryStream msb = new MemoryStream(KeyBytes))
{
Algorithm = new RijndaelManaged();
Algorithm.Key = PrivateKey.GetBytes(Algorithm.KeySize / 8);
Algorithm.IV = ReadByteArray(msb);
Algorithm.Padding = PaddingMode.PKCS7;
ICryptoTransform Decryption = Algorithm.CreateDecryptor(Algorithm.Key, Algorithm.IV);
using (CryptoStream csb = new CryptoStream(msb, Decryption, CryptoStreamMode.Read))
{
using (StreamReader srb = new StreamReader(csb))
{
Output = srb.ReadToEnd();
}
}
}
}
finally
{
if (Algorithm != null)
{
Algorithm.Clear();
}
}
return Output;
}
public static string Sha512(string ToHash)
{
using (SHA512 SHA = new SHA512Managed())
{
byte[] HashByte = Encoding.UTF8.GetBytes(ToHash);
byte[] HashBytes = SHA.ComputeHash(HashByte);
string Hash = System.Text.Encoding.UTF8.GetString(HashBytes, 0, HashBytes.Length);
return Hash;
}
}
public static string Base64Encode(string data)
{
byte[] str = Encoding.UTF8.GetBytes(data);
return Convert.ToBase64String(str);
}
public static string Base64Decode(string data)
{
byte[] str = Convert.FromBase64String(data);
return Encoding.UTF8.GetString(str);
}
private byte[] ReadByteArray(Stream st)
{
byte[] Length = new byte[sizeof(int)];
st.Read(Length, 0, Length.Length);
byte[] Buffer = new byte[BitConverter.ToInt32(Length, 0)];
st.Read(Buffer, 0, Buffer.Length);
return Buffer;
}
}
}
I've been arguing with this today with smartcards (or more accurately, a Yubikey Neo with the smartcard PIV applet enabled); using this code:
var encryptor = (RSACryptoServiceProvider)c.PublicKey.Key;
var decryptor = (RSACryptoServiceProvider)c.PrivateKey;
var encrypt = encryptor.Encrypt(bytes, RSAEncryptionPadding.Pkcs1);
var decrypt = decryptor.Decrypt(encrypt, RSAEncryptionPadding.Pkcs1);
I've found that it matters what padding algo I use. If I use PKCS1 padding, everything works. If I use OaepSHA1, I get the Error while decoding [...] error. If I use anything else (e.g., OaepSHA256) I get a Not supported error.
I can only conclude that my smartcard doesn't properly support OAEP SHA1, but padding with PKCS#1 everything is good.
Even if this answers what you already know, it may be useful as another datapoint for anyone else coming along using smartcards.
Make sure your key size is not too small or too large.
See comments from MSDN
The RSACryptoServiceProvider supports key sizes from 384 bits to 16384
bits in increments of 8 bits if you have the Microsoft Enhanced
Cryptographic Provider installed. It supports key sizes from 384 bits
to 512 bits in increments of 8 bits if you have the Microsoft Base
Cryptographic Provider installed.
So you might need to pad short key strings with some bytes to get the minimum key length
Ok, I managed to check this and from what I can see, I have problems with some certificates. I am not sure why some certificates work while others don't. It would be good to know why some certificates fail in this case?
Anyway, I created a new self signed certificate using windows "Manage File Encryption Certificates" and used this certificate, and all seems to work.
The out put from your code.
Encryption Key: aUc/GXWDoh2LktaEGeCJfju1dHP118yD/fzfT0iJLuhOq2QeyGpG6m3aBHaxvdH0ufeXRHbMjmlmPgIL/bhABzkT2C5Oa6ZhY3IFXb5t7JXZ3AtUunvtNAnRyFJ7MzklrSZGgQ
vF67DSNfIVE17doKt6j6mkCpSco56ooZCrOs2Mp3vSXqNjvjiwMEfQbk41aYUNVNVNlBGhdNQCIZIAKezQCUpWqzn2II27FIDfqDIEW4ieyzpXC05GzUlGXDxFOiFUPk3n0Y94vgeF8AlCD74eyZtz
WQ==
Encrypted Body: EAAAANS/W7+GGRbT1q5NCYvZlDZYtxaA8g55HzUqP5qxhenn
Encrypted Decryption Key: vc/tcsApmY1503BFi7oSu/RDvZivA1Ed58KJuLoEC6eE8q0BIa6ye2JvtXyxkVbzzL0MA51pZ2ZhMIsfCnBsEDjCgy+JLTZTGM1Mv+em9frFUKb0zHbICnPUa/3H
yd1yOWsdn5ws19QN2dzC6eau+ExhT2T/vyZO4Nf9NdHKnB8n2yB1rrQ/T+N2EYCNH/AVPDAsme6JG7k9Od2XIipBXMyCgXgWYZmQusq+JQjA9d3c4CrQYcg/ERF+K3oZv/gPicBkAR5taxwSxAajGg
bpkJNsbhTMHTN9bOn333qZ6ojlo5e882baZXuZWPr9qtj1b7ONoOyuSx/OvGKjt93BQg==
Decrypted Body: Hello World!
Output String: Hello World!.
Hope that helps
My question is pretty similar to the one form 2011, Signing and verifying signatures with RSA C#. Nevertheless, I also get false when I compare the signed data and the original message. Please point on my mistake.
Code:
public static void Main(string[] args)
{
//Generate a public/private key pair.
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
//Save the public key information to an RSAParameters structure.
RSAParameters RSAPublicKeyInfo = RSA.ExportParameters(false);
RSAParameters RSAPrivateKeyInfo = RSA.ExportParameters(true);
string message = "2017-04-10T09:37:35.351Z";
string signedMessage = SignData(message, RSAPrivateKeyInfo);
bool success = VerifyData(message, signedMessage, RSAPublicKeyInfo);
Console.WriteLine($"success {success}");
Console.ReadLine();
}
Signing method:
public static string SignData(string message, RSAParameters privateKey)
{
ASCIIEncoding byteConverter = new ASCIIEncoding();
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
// Write the message to a byte array using ASCII as the encoding.
byte[] originalData = byteConverter.GetBytes(message);
try
{
// Import the private key used for signing the message
rsa.ImportParameters(privateKey);
// Sign the data, using SHA512 as the hashing algorithm
signedBytes = rsa.SignData(originalData, CryptoConfig.MapNameToOID("SHA512"));
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
return null;
}
finally
{
// Set the keycontainer to be cleared when rsa is garbage collected.
rsa.PersistKeyInCsp = false;
}
}
// Convert the byte array back to a string message
return byteConverter.GetString(signedBytes);
}
Verification method:
public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
{
bool success = false;
using (var rsa = new RSACryptoServiceProvider())
{
ASCIIEncoding byteConverter = new ASCIIEncoding();
byte[] bytesToVerify = byteConverter.GetBytes(originalMessage);
byte[] signedBytes = byteConverter.GetBytes(signedMessage);
try
{
rsa.ImportParameters(publicKey);
success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes);
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
return success;
}
Basically the problem is with string to byte[] encoding. I get the same problem with ASCIIEncoding and with UTF8Encoding.
Thank you in advance!
You cannot use ASCIIEncoding on the encoded message because it contains bytes which are invalid ASCII characters. The typical way you would store the encoded message is in a base64 string.
In SignData, use the following to encode the byte array into a string:
return Convert.ToBase64String(signedBytes);
and in VerifyData, use the following to decode the string back to the same byte array:
byte[] signedBytes = Convert.FromBase64String(signedMessage);
I need to sign the string with private Key using RSA phpseclib and then verify it in C# . I have seen many examples of how to encrypt in C# and decrypt in php, but none of how to sign string in php and verify in .NET.
here is php code:
include('Crypt/RSA.php');
$info = "Something";
$PrivateKey= "<RSAKeyValue><Modulus>3C5QWo4H+............"; //long string
$unsignedString = base64_encode($info);
$signedString = HashAndSignBytes($info, $PrivateKey);
file_put_contents('file.txt', $unsignedString."\n".$signedString);
function HashAndSignBytes($stringToSign, $Key) {
$rsa = new Crypt_RSA();
$rsa->loadKey($Key); // private key
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$signature = $rsa->sign($stringToSign);
return base64_encode($signature);
}
and here is my attempt to read the file and verify it in C#:
const string publicKey = #"<RSAKeyValue><Modulus>3C5QWo4H.....";
TextReader reader = new StreamReader(path, Encoding.ASCII);
var unsignedString = reader.ReadLine();
var signedString = reader.ReadLine();
reader.Close();
if (VerifySignedHash(unsignedString,signedString, publicKey)) {
//some code
}
private bool VerifySignedHash(string stringToVerify, string signedString, string publicKey)
{
var byteConverter = new ASCIIEncoding();
var dataToVerify = Convert.FromBase64String(stringToVerify);
var signedData = Convert.FromBase64String(signedString);
try
{
// Create a new instance of RSACryptoServiceProvider using the
// key from RSAParameters.
var rsaAlg = new RSACryptoServiceProvider();
rsaAlg.FromXmlString(publicKey);
// Verify the data using the signature. Pass a new instance of SHA1CryptoServiceProvider
// to specify the use of SHA1 for hashing.
return rsaAlg.VerifyData(dataToVerify, new SHA1CryptoServiceProvider(), signedData);
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
return false;
}
}
verfication fails...
In your "signing" code, you base64encode the original string, then write that string to the output file. However, on the C# side, you read that value into unsignedString, but never reverse the base64 encoding.
The end result is that you're trying to verify the bytes of the base64Encoded string, not the data itself, so the VerifyData step fails.
Think that's your problem.
Modifying the following line might solve the problem:
var dataToVerify = Convert.FromBase64String(stringToVerify);
I recently posted about issues with encrypting large data with RSA, I am finally done with that and now I am moving on to implementing signing with a user's private key and verifying with the corresponding public key. However, whenever I compare the signed data and the original message I basically just get false returned. I am hoping some of your could see what I am doing wrong.
Here is the code:
public static string SignData(string message, RSAParameters privateKey)
{
//// The array to store the signed message in bytes
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
//// Write the message to a byte array using UTF8 as the encoding.
var encoder = new UTF8Encoding();
byte[] originalData = encoder.GetBytes(message);
try
{
//// Import the private key used for signing the message
rsa.ImportParameters(privateKey);
//// Sign the data, using SHA512 as the hashing algorithm
signedBytes = rsa.SignData(originalData, CryptoConfig.MapNameToOID("SHA512"));
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
return null;
}
finally
{
//// Set the keycontainer to be cleared when rsa is garbage collected.
rsa.PersistKeyInCsp = false;
}
}
//// Convert the a base64 string before returning
return Convert.ToBase64String(signedBytes);
}
So that is the first step, to sign the data, next I move on to verifying the data:
public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
{
bool success = false;
using (var rsa = new RSACryptoServiceProvider())
{
byte[] bytesToVerify = Convert.FromBase64String(originalMessage);
byte[] signedBytes = Convert.FromBase64String(signedMessage);
try
{
rsa.ImportParameters(publicKey);
SHA512Managed Hash = new SHA512Managed();
byte[] hashedData = Hash.ComputeHash(signedBytes);
success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes);
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
return success;
}
And here is the test client:
public static void Main(string[] args)
{
PublicKeyInfrastructure pki = new PublicKeyInfrastructure();
Cryptograph crypto = new Cryptograph();
RSAParameters privateKey = crypto.GenerateKeys("email#email.com");
const string PlainText = "This is really sent by me, really!";
RSAParameters publicKey = crypto.GetPublicKey("email#email.com");
string encryptedText = Cryptograph.Encrypt(PlainText, publicKey);
Console.WriteLine("This is the encrypted Text:" + "\n " + encryptedText);
string decryptedText = Cryptograph.Decrypt(encryptedText, privateKey);
Console.WriteLine("This is the decrypted text: " + decryptedText);
string messageToSign = encryptedText;
string signedMessage = Cryptograph.SignData(messageToSign, privateKey);
//// Is this message really, really, REALLY sent by me?
bool success = Cryptograph.VerifyData(messageToSign, signedMessage, publicKey);
Console.WriteLine("Is this message really, really, REALLY sent by me? " + success);
}
Am I missing a step here? According to the Cryptography API and the examples there, I shouldn't manually compute any hashes, since I supply the algorithm within the method call itself.
Any help will be greatly appreciated.
Your problem is at the beginning of the VerifyData method:
public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
{
bool success = false;
using (var rsa = new RSACryptoServiceProvider())
{
//Don't do this, do the same as you did in SignData:
//byte[] bytesToVerify = Convert.FromBase64String(originalMessage);
var encoder = new UTF8Encoding();
byte[] bytesToVerify = encoder.GetBytes(originalMessage);
byte[] signedBytes = Convert.FromBase64String(signedMessage);
try
...
For some reason you switched to FromBase64String instead of UTF8Encoding.GetBytes.