Return to HomePage




Validate an RSA signature of a given message (VB.NET)


Applies to

* .NET 2.0
* VB.NET


Summary

This code demonstrates validation of an RSA signature for a given message received from another entity. The RSA signature can be used to perform integrity checking and provides non-repudiation for the message sent by another entity.

Objectives

* To validate a cryptographic public key signature of a given message, to be used to validate integrity checks on data stored for periods of time or on transmitted data.
* To provide non-repudiation of a message or piece of data which can be independently validated by users who posess the RSA public key.


Scenarios

* Two entities in a client-server or client-client architecture need to transmit data with a mechanism to validate the authenticity of the sender and provide non-repududiation.
* An application stores files for prolonged periods of time. The developer wants to provide non-repudiation of files stored to ensure they aren't altered over time.


Solution Example

		    ' In RSA signatures a message is verified by performing a hash of the original message
		    ' and performing a public key operation (exponentiation)
		    Public Function [VerifyMessageSignature(ByVal] message() As Byte, [ByVal] sig() As Byte, [ByVal] pubkey As [RSAParameters)] As Boolean
		        Dim [isValidSig] As Boolean = False
		        Dim [myRsaProvider] As [RSACryptoServiceProvider] = New [RSACryptoServiceProvider()]
	

		        ' Import the sender's public key
		        [myRsaProvider.ImportParameters(pubkey)]
	

		        [isValidSig] = [myRsaProvider.VerifyData(message,] New [SHA1CryptoServiceProvider(),] sig)
		        Return [isValidSig]
		    End Function
	


Problem Example

Perhaps the most common pitfall developers encounter when communicating with a remote node over a public communications channel is the failure to perform any message signing such as that implemented by our Solution Example.

The next most common pitfall is to simply perform a hashed digest of the message using a public hashing algortihm demonstrated below:

		        Public Function [GenerateDigest(ByVal] input As String) As String
	

		            ' Instantiate the SHA1 Digest
		            Dim sha As SHA1 =  New [SHA1CryptoServiceProvider()] 
		            Return [ASCIIEncoding.ASCII.GetString(sha.ComputeHash(ASCIIEncoding.ASCII.GetBytes(input)))]
		        End Function
	

' Then later in code the user validates the signature of the message comparing hashes
' to test for message authenticity
If GenerateDigest(message).Equals(digest) Then
Boolean isValidSig = True
End If

* If a message is intercepted in transit or modified in storage, an attacker may simply perform their own hash representation of the value to be included in the communications or stored along with the file on disk.

Test Case

The following classes must be included in any project making use of the
sample code provided above:

Imports System.Text
Imports System.Security
Imports System.Security.Cryptography

		    Sub [Main(ByVal] args() As String)
		        ' Create a test keypair with a strong keysize of 2048 bits. In a production application 
		        ' we would load this value from a DPAPI protected registry value
		        Dim rsaProvider As [RSACryptoServiceProvider] = New [RSACryptoServiceProvider(2048)]
	

		        ' The [ExportParameters] method below takes a boolean, which determines whether
		        ' to export the private key data within the parameters. When exporting parameters
		        ' ensure that only the public key parameter is shared with the remote party:
		        Dim [rsaPubKeyParams] As [RSAParameters] = [rsaProvider.ExportParameters(False)]
	

		        ' We'll also export the private key for our signing operations
		        Dim [rsaPrivKeyParams] As [RSAParameters] = [rsaProvider.ExportParameters(True)]
	


		        Dim message1 As String = "the quick brown fox jumped over the lazy dog"
		        Dim message2 As String = "the quick brown dog jumped over the lazy fox"
	

		        Dim sig() As Byte = [SignMessage(ASCIIEncoding.ASCII.GetBytes(message1),] [rsaPrivKeyParams)]
		        Console.Out.WriteLine("MSG: " + message1)
		        Console.Out.WriteLine("\nRSA Sig: " + [Convert.ToBase64String(sig))]
	

		        Console.Out.WriteLine("\nTest Case #1:")
		        Console.Out.WriteLine("Validating signature for MSG: " + message1)
		        If [VerifyMessageSignature(ASCIIEncoding.ASCII.GetBytes(message1),] sig, [rsaPubKeyParams)] Then
		            Console.Out.WriteLine("Valid signature.")
		        Else
		            Console.Out.WriteLine("Invalid signature.")
		        End If
	

		        Console.Out.WriteLine("\nTest Case #2:")
		        Console.Out.WriteLine("Validating signature for MSG: " + message2)
		        If [VerifyMessageSignature(ASCIIEncoding.ASCII.GetBytes(message2),] sig, [rsaPubKeyParams)] Then
		            Console.Out.WriteLine("Valid signature.")
		        Else
		            Console.Out.WriteLine("Invalid signature.")
		        End If
		    End Sub
	



Expected Result

Running the test case above will result in the following output:

MSG: the quick brown fox jumped over the lazy dog

RSA Sig: E1uGW7OmhpoP9LgnjfLA7IWUQhlrxL87tmHnkqGPowCssX70ftT78T4mE5lF5iog4elIgBTUH5miVJdsqKXzTBK64V+
W5gCUqsESiqcmJztchpbeyc0E9tqNBaFlo+8yiSp6aIsDsS9W5OsNgnj0Tn3vT2vnRqWA8qORLmifVrPXtQU4gm60sHO2RKiTsiM
u81m3MfNI3Is/MadLn6bwxnnvDNxJFpDADENaihVdBSrIDeEV4CBaQE59GbJJSBBfY15xC5X0ufNske0eG+k3LURJeQDSg03oFNB
HMi8ZL7oTaWHw0xRygh/aBqZCTEtTjj+RsLPxv5NsrxhzSFXlDw==

Test Case #1:
Validating signature for MSG: the quick brown fox jumped over the lazy dog
Valid signature.

Test Case #2:
Validating signature for MSG: the quick brown dog jumped over the lazy fox
Invalid signature.


More Information

Potential pitfalls in secure communications include session replay attacks. Session replay may be mitigated through use of RSA signatures in which a message includes a timestamp or session identifier to be used once. By performing an RSA signature on the message it is possible to protect against session replay because only the sender can generate a valid signature of a message given the properties of asymmetric encryption algorithms.

Perhaps the single most important design consideration in a secure communication protocol is to include message signing altogether. However, Asymmetric encryption routines are expensive and generally performed during the initial key exchange process during which two entities agree on a common shared (secret - symmetric) key to be used in a more efficient HMAC algorithm.

Care should be taken in storage of the private key pair. Ensure that keys are stored within a container (for more information please refer to: http://msdn2.microsoft.com/en-us/library/system.security.cryptography.cspparameters(VS.80).aspx).

When sharing keys with a remote entity always ensure only the public key data is exported rather than the full RSA key. To export only the private key one may call the following methods:

		 ' The [ExportParameters] method below takes a boolean, which determines whether
		 ' to export the private key data within the parameters. When exporting 
		 ' parameters ensure that only the public key parameter is shared with the 
		 ' remote party:
		            [rsaPubKeyParams] = [rsaProvider.ExportParameters(false)]
	

Or alternatively export just the public key data as XML:

' Setting the argument to false ensures that the private
' key is not exported.
		            [rsaPubString] = [myRsaProvider.ToXmlString(false)]
	

Additional Resources

* RSA Encrycryption / Signing: http://en.wikipedia.org/wiki/RSA
* Crytopgraphy (.NET): http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGGuidelines0003.asp?frame=true#pagguidelines0003_cryptography

Attributes

* Applies To: .NET Framework 2.0, VB
* Category: Cryptography
* Author: George Gal




Return to HomePage
Microsoft Communities