Signing data

To prove that some data has come from someone we trust, it can be signed. Actually, you don't sign the data itself; instead, you sign a hash of the data. We will use the RSA algorithm combined with the SHA256 algorithm.

Signing with SHA256 and RSA

In the Ch11_CryptographyLib class library project, add the following code to the Protector class:

    public static string PublicKey; 
 
    public static string ToXmlString( 
      this RSA rsa, bool includePrivateParameters) 
    { 
      var p = rsa.ExportParameters(includePrivateParameters); 
      XElement xml; 
      if (includePrivateParameters) 
      { 
        xml = new XElement("RSAKeyValue" 
          , new XElement("Modulus", Convert.ToBase64String(p.Modulus)) 
          , new XElement("Exponent",  
            Convert.ToBase64String(p.Exponent)) 
          , new XElement("P", Convert.ToBase64String(p.P)) 
          , new XElement("Q", Convert.ToBase64String(p.Q)) 
          , new XElement("DP", Convert.ToBase64String(p.DP)) 
          , new XElement("DQ", Convert.ToBase64String(p.DQ)) 
          , new XElement("InverseQ",  
            Convert.ToBase64String(p.InverseQ)) 
        ); 
      } 
      else 
      { 
        xml = new XElement("RSAKeyValue" 
          , new XElement("Modulus", Convert.ToBase64String(p.Modulus)) 
          , new XElement("Exponent",  
            Convert.ToBase64String(p.Exponent)) 
        ); 
      } 
      return xml?.ToString(); 
    } 
 
    public static void FromXmlString( 
      this RSA rsa, string parametersAsXml) 
    { 
      var xml = XDocument.Parse(parametersAsXml); 
      var root = xml.Element("RSAKeyValue"); 
      var p = new RSAParameters 
      { 
        Modulus = Convert.FromBase64String( 
          root.Element("Modulus").Value), 
        Exponent = Convert.FromBase64String( 
          root.Element("Exponent").Value) 
      }; 
      if(root.Element("P") != null) 
      { 
        p.P = Convert.FromBase64String(root.Element("P").Value); 
        p.Q = Convert.FromBase64String(root.Element("Q").Value); 
        p.DP = Convert.FromBase64String(root.Element("DP").Value); 
        p.DQ = Convert.FromBase64String(root.Element("DQ").Value); 
        p.InverseQ = Convert.FromBase64String( 
          root.Element("InverseQ").Value); 
      } 
      rsa.ImportParameters(p); 
    } 
 
    public static string GenerateSignature(string data) 
    { 
      byte[] dataBytes = Encoding.Unicode.GetBytes(data); 
      var sha = SHA256.Create(); 
      var hashedData = sha.ComputeHash(dataBytes); 
 
      var rsa = RSA.Create(); 
      PublicKey = rsa.ToXmlString(false); // exclude private key 
 
      return Convert.ToBase64String(rsa.SignHash(hashedData,  
        HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); 
    } 
 
    public static bool ValidateSignature( 
      string data, string signature) 
    { 
      byte[] dataBytes = Encoding.Unicode.GetBytes(data); 
      var sha = SHA256.Create(); 
      var hashedData = sha.ComputeHash(dataBytes); 
 
      byte[] signatureBytes = Convert.FromBase64String(signature); 
 
      var rsa = RSA.Create(); 
      rsa.FromXmlString(PublicKey); 
 
      return rsa.VerifyHash(hashedData, signatureBytes, 
        HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); 
    }

Note the following:

  • I have recreated two useful methods that exist on the RSA type in the .NET Framework: ToXmlString and FromXmlString. These serialize and deserialize the RSAParameters structure that contains the public and private keys. .NET Core's implementation of RSA does not include them.
  • Only the public part of the public-private key pair needs to be made available to the code that is checking the signature so that we can pass the value false when we call the ToXmlString method.
  • The hash algorithm used to generate the hash from the data must match the hash algorithm set on the signer and checker. In the preceding code, we used SHA256.

Add a new console application project named Ch11_SigningApp. Add a reference to the Ch11_CryptographyLib assembly, and then import the following namespaces:

    using static System.Console; 
    using Packt.CS7; 

In the Main method, add the following code:

    Write("Enter some text to sign: "); 
    string data = ReadLine(); 
    var signature = Protector.GenerateSignature(data); 
    WriteLine($"Signature: {signature}"); 
    WriteLine("Public key used to check signature:"); 
    WriteLine(Protector.PublicKey); 
 
    if (Protector.ValidateSignature(data, signature)) 
    { 
      WriteLine("Correct! Signature is valid."); 
    } 
    else 
    { 
      WriteLine("Invalid signature."); 
    } 
 
    // create a fake signature by replacing the  
    // first character with an X 
    var fakeSignature = signature.Replace(signature[0], 'X'); 
    if (Protector.ValidateSignature(data, fakeSignature)) 
    { 
      WriteLine("Correct! Signature is valid."); 
    } 
    else 
    { 
      WriteLine($"Invalid signature: {fakeSignature}"); 
    } 

Run the console application and enter some text:

Enter some text to sign: The cat sat on the mat.
Signature:
LSmfgRuRRvYzM1/jg7U7jkKINCU4KKGpFUCvCB87hmWpa3gDVLjLj0Wift+CktZuPSkc/ gAnIzC1bQCOyELsrNWzATnPDFa/B0Gpy0vAJ8VJ9FPs1vFy353mMnGcnQU8fOummKgEv4 r1JpsnkJQ41MGUMNCH9YVodO6Bn6o81g0=
Public key used to check signature:
<RSAKeyValue><Modulus>qPnY4UHIqJMuUJ0CQ4F0Xy/fxaugNFFe/QNikGsufdKrwa1 t+CcQqCmWso4zUDW3NTFCWFGilisJ4SqTBgYee/VT9UGuFng68TrZXNiNJO8dP8OZHNBi rWkhtsNQx9A6rq9bZ/9dsjY1hYsWpGKCw4WhxsHjmGuevQew8C+I2z0=</Modulus><Ex
ponent>AQAB</Exponent></RSAKeyValue>
Correct! Signature is valid.
Invalid signature:
X1uDRfCDXvOyhMtqXlxqzSljhADD/81E0UonuVs9VfZ7ceuyFWh4O7rwkdc1+l25DzGf6 4swtbXZsukpSupFqvkAOIJ6XqMlD92vlG1nquereiWkshYnxxVts30QJIFKKyOTBTfN/V OljlZVMxT/RA6pggPtESlv+urDJT4z/PEtR5jdx+CTZHQc9WiceFbpuybyf/vEdddtF0T 7g8NeLKEPbT6b7CHGDM1HKbRqnSecv456QNfHNmEXxRk9MpI0DgQLnXpOhHcVwEFc6+dY 6kdNnWd6NIOY3qX6FT782t0lQ2swcWxF9fUcvWVSeC84EgVK447X9Xewkrf6CF7jxg==
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.224.226