Implementing Digital Signing in .NET






4.60/5 (33 votes)
Nov 25, 2004
4 min read

295715

9618
Implements digital signing using .NET framework.
Introduction
This tutorial will show how to achieve digital signing in .NET framework 1.1 using System.Security.Cryptography
class.
Digital Signatures
Digital signatures are used to achieve Authentication, Non-repudiation, and Authorization.
Authentication is a technique by which a process verifies that its communication partner is who it is supposed to be and not an intruder, and deals with the question of whether or not you are actually communicating with a specific process. Non-repudiation is a mechanism which provides a way to prevent the author from falsely claming that he or she isn’t the author. Authorization is concerned with what that process is permitted to do.
Let’s say Alice and Bob decide to sign digitally, a contract between them which is highly confidential. Here’s the protocol they can use to digitally sign the contact:
- Alice and Bob each get a copy of the file containing the contract.
- Bob prepares a message and computes the hash of it and encrypts the hash value with his private key called Signature Block.
- Then he encrypts the message with Alice's Public Key.
- He sends two files to Alice: encrypted hash and message.
- Upon receiving, Alice decrypts hash value with Bob's public key.
- Then she decrypts message with her private key.
- She then computes the hash of this message.
- Finally, she compares the two hash values. If they are same, the signature is “good”, otherwise bad.
If Bob wants to cheat Alice, he has a big problem. Since Alice knows his RSA public key because she made it well private. Therefore, the entire encrypted message serves as a “digital signature”. So the message is authenticated both in terms of source and in terms of data integrity.
What is Hash?
Hashes are known as One way functions, that is their mathematical property of non reversibility. Further more, they are also known as Message digest functions because message is reduced or digest to a fixed-length number that is smaller than the message. Hashes are the actual sum of ASCII values of all letters of message, and no matter how long the input data is, the hash is always the same number of bits.
.NET provides us with following Hash algorithms:
MD5CryptoServiceProvider
(Message digest 5)SHA1CryptoServiceProvider
(Secure hash algorithm with key size 160-bits)SHA256Managed
(Secure hash algorithm with key size 256-bits)SHA384Managed
(Secure hash algorithm with key size 384-bits)SHA512Managed
(Secure hash algorithm with key size 512-bits)HMACSHA1
(Hash-based Message Authentication Code using the SHA1 hash function)MACTripleDES
(Message Authentication Code using the TripleDES for the input data)
Also, .NET provides us with following Digital Signature Algorithms:
DSACryptoServiceProvider
(Digital Signature Algorithm)RSACryptoServiceProvider
(Rivest, Shamir and Adlemen)
We will use RSA algorithm since it can be used not only for digital signatures, but for also encryption and decryption. It is tiny but a bit faster than DSA algorithm which can only be used for digital signing, issued by NIST (National Institute of Standards and Technology).
Let us implement this concept in .NET framework 1.1.
Implementation
Start a new Windows Application project and assign a name “digital signing” and do the following”:
Add a new form names FORM1
with controls on it as: (Interface should be like the form as shown below: for more clarity, download code)
GroupBox
named Bob (sender) with following controls on it:Label
control, threeTextBox
es for output.- A
Button
namedButton1
withText
property as “&Encrypt Plaintext using Receiver's (Alice) Public Key”. - A
Button
namedButton1
withText
property as “Generate &Signature Block using Sender's (Bob) Private Key”.
GroupBox
named Alice (receiver) with following controls on it:- A
TextBox
control for output. - A
Button
namedButton3
withText
property as “Verify Signature block using sender's (Bob) Public Key”. - A
Button
namedButton4
withText
property as “&Decrypt plaintext using receiver (Alice) private key”.
- A
- A
Button
namedButton5
which is the Exit button.
Form1
That’s all for the interface. Now, it's time for coding. Let’s start it:
Code listing for “Form1”:
Imports System.Text
Public Class Form1 ‘Main interface form
Inherits System.Windows.Forms.Form
Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click
'Verify the signature is authentic using
'the sender's public key(decrypt Signature block)
If myReceiver.VerifyHash(mySender.PublicParameters, _
encrypted, signature) Then
MsgBox("Signature Valid", MsgBoxStyle.Information)
Button4.Enabled = True
Else
MsgBox("Invalid Signature", MsgBoxStyle.Exclamation)
Button4.Enabled = False
End If
End Sub
Private Sub Button1_Click_1(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
If Me.TxtPlainText.Text = "" Then
MsgBox("Please enter a string to sign", MsgBoxStyle.Information)
Exit Sub
End If
'Convert the data string to a byte array.
toEncrypt = enc.GetBytes(TxtPlainText.Text)
'Encrypt data using receiver's public key.
encrypted = mySender.EncryptData(myReceiver.PublicParameters, toEncrypt)
'convert to base64/Radix output
TextBox1.Text = Convert.ToBase64String(encrypted)
Me.Button2.Enabled = True
End Sub
Private Sub Button2_Click_1(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
'Hash the encrypted data and generate a signature block on the hash
' using the sender's private key. (Signature Block)
signature = mySender.HashAndSign(encrypted)
'convert to base64/Radix output
TextBox2.Text = Convert.ToBase64String(encrypted)
Me.Button3.Enabled = True
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button4.Click
TextBox3.Text = myReceiver.DecryptData(encrypted)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Button2.Enabled = False
Button3.Enabled = False
Button4.Enabled = False
End Sub
Private Sub Button5_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button5.Click
myReceiver = Nothing
mySender = Nothing
End
End Sub
End Class
Now, do the following:
- Add a
Class
to project and name it “Bob” which plays a role of sender. - Add another
Class
and name it “Alice” which plays a role of receiver. - Add a
Module
named “Global” for global declarations of variables.
Code listing for Class “Bob”:
Imports System.Security.Cryptography
Imports System.Text
Public Class Bob
'=======================================================
‘Bob Sender is who want to exchange and prepares a encrypted message
'=======================================================
Private rsaPubParams As RSAParameters 'stores public key
Private rsaPrivateParams As RSAParameters 'stores private key
Public Sub New()
'create new instance of RSACryptoServiceProvider
Dim rsaCSP As New RSACryptoServiceProvider
'Generate public and private key data and allowing their exporting.
'True to include private parameters; otherwise, false
rsaPrivateParams = rsaCSP.ExportParameters(True)
rsaPubParams = rsaCSP.ExportParameters(False)
End Sub 'New
Public ReadOnly Property PublicParameters() As RSAParameters
Get
'just return public key
Return rsaPubParams
End Get
End Property
'Manually performs hash and then signs hashed value.
Public Function HashAndSign(ByVal encrypted() As Byte) As Byte()
'create new instance of RSACryptoServiceProvider
Dim rsaCSP As New RSACryptoServiceProvider
'create new instance of SHA1 hash algorithm to compute hash
Dim hash As New SHA1Managed
'a byte array to store hash value
Dim hashedData() As Byte
'import private key params into instance of RSACryptoServiceProvider
rsaCSP.ImportParameters(rsaPrivateParams)
'compute hash with algorithm specified as here we have SHA!
hashedData = hash.ComputeHash(encrypted)
' Sign Data using private key and OID is simple name
' of the algorithm for which to get the object identifier (OID)
Return rsaCSP.SignHash(hashedData, CryptoConfig.MapNameToOID("SHA1"))
End Function 'HashAndSign
'Encrypts using only the public key data.
Public Function EncryptData(ByVal rsaParams As RSAParameters, _
ByVal toEncrypt() As Byte) As Byte()
'create new instance of RSACryptoServiceProvider
Dim rsaCSP As New RSACryptoServiceProvider
''import private key params into instance of RSACryptoServiceProvider
rsaCSP.ImportParameters(rsaParams)
'true to use OAEP padding PKCS#1 v2 (only available on Windows XP or later)
' otherwise, false to use Direct Encryption using PKCS#1 v1.5 padding
Return rsaCSP.Encrypt(toEncrypt, False)
End Function 'EncryptData
End Class 'Bob
Code listing for Class “Alice”:
Imports System.Security.Cryptography
Imports System.Text
Public Class Alice
'=========================================
' Alice is Receiver who will decrypt data from sender
'========================================
Private rsaPubParams As RSAParameters ' stores public key
Private rsaPrivateParams As RSAParameters 'stores private key
Public Sub New()
'create new instance of RSACryptoServiceProvider
Dim rsaCSP As New RSACryptoServiceProvider
'Generate public and private key data and allowing their exporting.
'True to include private parameters; otherwise, false
rsaPrivateParams = rsaCSP.ExportParameters(True)
rsaPubParams = rsaCSP.ExportParameters(False)
End Sub 'New
Public ReadOnly Property PublicParameters() As RSAParameters
Get
'Just return public key
Return rsaPubParams
End Get
End Property
'Manually performs hash and then verifies hashed value.
Public Function VerifyHash(ByVal rsaParams As RSAParameters, _
ByVal signedData() As Byte, _
ByVal signature() As Byte) As Boolean
'create new instance of RSACryptoServiceProvider
Dim rsaCSP As New RSACryptoServiceProvider
'create new instance of SHA1 hash algorithm to compute hash
Dim hash As New SHA1Managed
'a byte array to store hash value
Dim hashedData() As Byte
'import public key params into instance of RSACryptoServiceProvider
rsaCSP.ImportParameters(rsaParams)
'compute hash with algorithm specified as here we have SHA1
hashedData = hash.ComputeHash(signedData)
' Sign Data using public key and OID is simple name
' of the algorithm for which to get the object identifier (OID)
Return rsaCSP.VerifyHash(hashedData, _
CryptoConfig.MapNameToOID("SHA1"), signature)
End Function 'VerifyHash
'Decrypt using the private key data.
Public Function DecryptData(ByVal encrypted() As Byte) As String
'a byte array to store decrypted bytes
Dim fromEncrypt() As Byte
' holds orignal message
Dim roundTrip As String
'create new instance of RSACryptoServiceProvider
Dim rsaCSP As New RSACryptoServiceProvider
'import private key params into instance of RSACryptoServiceProvider
rsaCSP.ImportParameters(rsaPrivateParams)
'store decrypted data into byte array
fromEncrypt = rsaCSP.Decrypt(encrypted, False)
'convert bytes to string
roundTrip = enc.GetString(fromEncrypt)
Return roundTrip
End Function 'DecryptData
End Class ’ Alice
Code listing for Module “Global”:
Imports System.Text
Module Global
'Hold message in bytes
Public toEncrypt() As Byte
'holds encrypted data
Public encrypted() As Byte
'holds signatures
Public signature() As Byte
'instance of class Bob
Public mySender As New Bob
'instance of class Alice
Public myReceiver As New Alice
'new instance of Unicode8 instance
Public enc As New UTF8Encoding
End Module
Running the Sample
In the Visual Studio .NET IDE, press the <F5> key. When you are done, click Exit button to close the program.
Conclusion
I am always willing to help, so if you have any questions, suggestions, about my article and code, then feel free to email me. You can also reach me on MSN messenger with screen name “Maxima”.