Click here to Skip to main content
Click here to Skip to main content

Implementing Digital Signing in .NET

, 25 Nov 2004
Rate this:
Please Sign up or sign in to vote.
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:

Sample screenshot

  1. Alice and Bob each get a copy of the file containing the contract.
  2. Bob prepares a message and computes the hash of it and encrypts the hash value with his private key called Signature Block.
  3. Then he encrypts the message with Alice's Public Key.
  4. He sends two files to Alice: encrypted hash and message.
  5. Upon receiving, Alice decrypts hash value with Bob's public key.
  6. Then she decrypts message with her private key.
  7. She then computes the hash of this message.
  8. 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)

Sample screenshot

  1. GroupBox named Bob (sender) with following controls on it:
    • Label control, three TextBoxes for output.
    • A Button named Button1 with Text property as “&Encrypt Plaintext using Receiver's (Alice) Public Key”.
    • A Button named Button1 with Text property as “Generate &Signature Block using Sender's (Bob) Private Key”.
  2. GroupBox named Alice (receiver) with following controls on it:
    • A TextBox control for output.
    • A Button named Button3 with Text property as “Verify Signature block using sender's (Bob) Public Key”.
    • A Button named Button4 with Text property as “&Decrypt plaintext using receiver (Alice) private key”.
  3. A Button named Button5 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”.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Adnan Samuel
Software Developer (Senior)
Pakistan Pakistan
I am software engineer and working from last four years in the information technology field. I love to do intresting tasks. I love to see diffrent places and listening muzik.

Comments and Discussions

 
QuestionVerifying digital signature need help PinmemberMember 1069332418-Jul-14 5:07 
GeneralMy vote of 5 Pinmemberviral.sharma6-May-13 1:06 
GeneralMy vote of 5 Pinmemberardiardianto24-Oct-12 7:17 
GeneralMy vote of 5 PinmemberMember 874252318-Oct-12 21:37 
Questionc# code for digital signature for email . Pinmemberseemakumari111-Aug-12 1:25 
QuestionNewbie Confused About Signing PinmemberAlanC1224-Jan-12 2:40 
GeneralGreat article .. but I have a problem PinmemberRadu_2017-Jun-08 3:38 
GeneralPlagarized From Microsoft Examples PinmemberCode Deamon17-Apr-08 13:31 
GeneralThx for the link PinmemberTachyonx13-Feb-13 7:04 
GeneralWrite(read) DSAParameters to file PinmemberVUIT25-Feb-08 17:25 
QuestionTextBox1.Text=TextBox2.Text ? PinmemberMember 83707624-Jan-08 17:36 
QuestionPersisting Keys? Pinmemberjoe@dnswebcreations.com6-Mar-07 6:49 
AnswerRe: Persisting Keys? Pinmemberk^s8-Mar-07 0:44 
GeneralRe: Persisting Keys? PinmemberJoe Sweeney8-Mar-07 6:34 
QuestionProblem While Digital Signing PinmemberFarid_0180123-Feb-07 22:19 
GeneralDigital Signature by Multiple X509Certificates PinmemberMember #36860026-Feb-07 19:50 
GeneralNice article! Pinmemberspinoza16-Jan-07 0:03 
QuestionSignature??? PinmemberPerley9-Oct-06 23:11 
AnswerRe: Signature??? Pinmembermarquesbrasil21-Apr-10 4:01 
GeneralActually where private and public key are generating PinmemberK.Gajalakshmi10-Sep-06 8:18 
QuestionIs there a sample code for ASP.NET 2.0 ? Pinmembergrigorythegreat10-Aug-06 3:00 
GeneralGreat for starters Pinmembershephie28-May-06 1:13 
GeneralNice PinmemberMonsterMike9-Apr-06 9:51 
GeneralMinor practical suggestions Pinmembermdastpak4-Mar-05 8:22 
AnswerRe: how do i do s/mime? PinmemberAdnan Samuel9-Jan-05 3:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 25 Nov 2004
Article Copyright 2004 by Adnan Samuel
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid