Documente Academic
Documente Profesional
Documente Cultură
A efectuat : A verificat:
Chisinau 2010
1 Sarcina lucrrii
Elaborarea unui sistem informatic care aplic semntura digital asupra fiierelor utiliznd algoritmi de semnare i verificare a semnturii digitale.
2 Algoritmul DSA
Algoritmul pentru semnturi digitale (englez: "Digital Signature Algorithm"), cunoscut i sub acronimul DSA, este un standard al guvernului Statelor Unite ale Americii pentru semnturile digitale. A fost propus de National Institute of Standards and Technology (NIST) n august 1991 pentru utilizare n cadrul standardului Digital Signature Standard (DSS), adoptat n 1993. O revizie minor a fost emis n 1996 sub numele de FIPS 186-1 , iar standardul a fost extins n 2000 sub numele FIPS 186-2 . Algoritmul este format din trei proceduri: generarea cheii, semnarea, verificarea semnturii.
, unde . . .
2.2 Semnarea
1 2 Se alege arbitrar .
Se calculeaz x=SHA-1(mesaj), cu x pe 160 de bii; SHA-1 este funcia de hash, care realizeaz rezumatul mesajului (returneaz un numr n funcie de coninutul mesajului).
3 4
Se calculeaz Se calculeaz 2
. .
Dac vreuna dintre cele dou valori ( sau ) este egal cu zero, atunci se reia calculul cu generarea unui alt k.
2.3 Verificarea
1 2 3 4 5 Se calculeaz Se calculeaz Se calculeaz Se calculeaz Semntura este valid dac i numai dac . . . . .
3 Realizarea aplicaiei
Scopul realizrii lucrrii date de laborator const n dezvoltarea unei aplicaii care ar verifica validitatea fiieilor utiliznd algorimul de semnare DSA. Astfel interfaa aplicaiei va fi constituit din dou seciuni: semanrea fiierilor i semanarea verificarea fiierilor. Astfel pentru nceput utilizatorul va trebui s selecteze fiierul (.pdf, .doc, .exe, .msi, .dll e.t.c) pentru a fi semant dup care selecteaz directoriia unde s salveze fiierele ce va conine cheia public i semnatura, utilizatorul mai are posibilitatea s specifice numele fiierelor pentru semntur i pentru cheia public. n seciunea de verificare a semnturilor utilizatorul trebuie s selecteze fiierul care urmeaz s fie verificat i fiierele unde sunt pstrate semntura degital i cheia public. n figura 1 este prezentat prototipul aplicaiei de verificare a semnturii digitale.
Pentru generarea cheiei publice i a celei private voi utiliza clasa DSACryptoServiceProvider dup care pentru calcularea hash-ului voi utiliza metoda ComputeHash a clasei SHA1. i pentru a semna mesajul voi apela metoda CreateSignature a clasei DSASignatureFormatter. Clasele DSACryptoServiceProvider, SHA1 i DSASignatureFormatter fac parte din spaiul de nume
System.Security.Cryptography. Nu am menionat la nceput c pentru a realiza aplicaia voi utiliza limbajul C# i posibilitile care le ofer framework-ul .NET. Semntura i cheia public vor fi pstrate n fiiere aparte, cheia public va fi pstrat ntr-un format XML. Funciile pentru semnarea i verificarea semnturii au fost extrase ntr-o clas Helpers. Pentru a vizualiza metodele clasei Helpers urmai figura 2.
Figura 2 Clasa Helpers Clasa Helpers conine metode pentru semnarea i verificarea fiierului, metode precum exportarea cheiei publice i imporarea ei dintr-un fiier XML, salvarea semnturii ntr-un fiier i opional metode pentru verificarea semnturii aplicate unui XML a crui realizare a fost opional. Mai jos voi continua cu fragmente din cod i cu diagrame de secvene care a explica fragmetul dat att codul ct i diagrama de secven vor fi nsoite de comentarii. n figura 3 vizualizai diagrama de secven a etapei de semnare a fiierului.
Figura 3 Diagrama de secven la etapa de semnare a fiierului Pentru semnarea fiierului sunt utilizate clasele DSACryptoServiceProvider i DSASignatureFormatter. Clasa DSACryptoServiceProvider este utilizat n contextul dat pentru generarea cheiei publice i celei private. Dup care pentru a semna mesajul este instaniat un obiect DSASignatureFormatter care primete n calitate de parametru un obiect DSACryptoServiceProvider. n continuare pentru indicarea algoritmului de creare a hash-ului este utilizat apelat metoda SetHashAlgorithm care primete n calitate de parametru algoritmul pentru realizarea hash-lui. Ultimul pas const n apelarea metodei CreateSignature pentru semnarea mesajului. Mai jos este prezentat fragmetul de cod descris cu ajutorul diagramei de secven.
try {
DSACryptoServiceProvider DSA = new DSACryptoServiceProvider(); DSA.ImportParameters(DSAKeyInfo); DSASignatureFormatter DSASignature = new DSASignatureFormatter(DSA); DSASignature.SetHashAlgorithm(HashAlgorithm); return DSASignature.CreateSignature(FileHashToSign); } catch (CryptographicException e) { return null; }
Pentru verificare semnturii fiierului sunt utilizate la fel clasele DSACryptoServiceProvider i DSASignatureFormatter. Pentru importarea cheiei publice este utilizat metoda FromXmlString clasei DSACryptoServiceProvider care primete n calitate de parametru iierul XML care conine cheia public. Pentru verificarea semnturii digitale este instaniat un obiect DSASignatureDeformatter care apeleaz metoda VerifySignature pentru a verifica semantura digital astfel el va primi ca parametru hash-ului fiierului i semntura digitl. Mai jos este prezentat fragmetul de cod.
try { DSACryptoServiceProvider dsaFromFile = new DSACryptoServiceProvider(); dsaFromFile.FromXmlString(publicXMLKeyFromFile); DSASignatureDeformatter verifier = new DSASignatureDeformatter(dsaFromFile); verifier.SetHashAlgorithm("SHA1"); return dsaFromFile.VerifySignature(rgbHash, rgbSignature); } catch (CryptographicException e) { return false; } catch (FormatException e) { return false; }
Figura 5 Aplicarea semnturii digitale asupra unui fiier Pop-up-ul din imagine indic faptul c fiierul a fost semnat cu succes. Pentru a demosntra performana algoritmului este deajuns s modificm coninutul semnturii sau a fiierului. Cea ce i am n gnd s fac.
Concuzie
Utilizarea algoritmului DSA pentru semnarea fiierilor este foarte eficient pe motiv c spargerea lui duce la rezolvarea unei probleme logaritmilor discrei care este foarte dificil. Implementarea algorimului DSA ultiznd framework-ul .NET este foarte simplu pe motiv c spaiul de nume System.Security.Cryptography conine clasele DSACryptoServiceProvider, SHA1 i DSASignatureFormatter care permit implementarea algorimilor DSA i clasa SHA1 care pune la dipoziie crearea hash-ului utiliznd algoritmul SHA1. Aplicaia dat are un mic neajuns pe motiv c cheia privat nu este pstrat ntr-un container de tip CspParameters. Pe lng realizarea aplicaiei de semnare am inclus n aplicaia dat o metod prelucat de pe MSDN de semnare a fiierilor XML.
Bibliografie
1 2 3 4 5 6 DIGITAL SIGNATURE STANDARD (DSS) - http://www.itl.nist.gov/fipspubs/fip186.htm DSACryptoServiceProvider Class - http://msdn.microsoft.com/enus/library/system.security.cryptography.dsacryptoserviceprovider.aspx DSASignatureFormatter Class - http://msdn.microsoft.com/enus/library/system.security.cryptography.dsasignatureformatter.aspx How to: Sign XML Documents with Digital Signatures - http://msdn.microsoft.com/enus/library/ms229745.aspx How to: Verify the Digital Signatures of XML Documents - http://msdn.microsoft.com/enus/library/ms229950.aspx SHA1 Class - http://msdn.microsoft.com/usen/library/system.security.cryptography.sha1.aspx 8
namespace Helpers { public static class Helpers { public static byte[] DSASignFile(byte[] FileHashToSign, DSAParameters DSAKeyInfo, string HashAlgorithm) { try { DSACryptoServiceProvider DSA = new DSACryptoServiceProvider(); DSA.ImportParameters(DSAKeyInfo); DSASignatureFormatter DSASignature = new DSASignatureFormatter(DSA); DSASignature.SetHashAlgorithm(HashAlgorithm); return DSASignature.CreateSignature(FileHashToSign); } catch (CryptographicException e) { return null; } } public static byte[] ComputeHash(byte[] FileToBeDSA) { try { SHA1 SHA = new SHA1CryptoServiceProvider(); return SHA.ComputeHash(FileToBeDSA); } catch (ArgumentNullException e) { return null; } } public static void ExportPublicKeyToXml(string PublicXMLKey, string XMLFile) { byte[] data = new ASCIIEncoding().GetBytes(PublicXMLKey); FileStream fsWrite = File.OpenWrite(XMLFile); try { fsWrite.SetLength(0);
public static void ExportSignatureToFile(byte[] Signature, string { try { File.WriteAllBytes(SignatureFile, Signature); } catch (IOException e) { }
public static string ImportPublicKeyFromXml(string XMLFile) { try { FileInfo fsInfo = new FileInfo(XMLFile); int fsInfoLength = Convert.ToInt32(fsInfo.Length); byte[] buffer = new byte[fsInfoLength + 1]; FileStream fsRead = File.OpenRead(XMLFile); fsRead.Read(buffer, 0, buffer.Length); fsRead.Close(); return new ASCIIEncoding().GetString(buffer); } catch (UnauthorizedAccessException e) { return null; } } public static bool DSAVerifyFile(string publicXMLKeyFromFile, byte[] rgbHash, byte[] rgbSignature) { try { DSACryptoServiceProvider dsaFromFile = new DSACryptoServiceProvider(); dsaFromFile.FromXmlString(publicXMLKeyFromFile); DSASignatureDeformatter verifier = new DSASignatureDeformatter(dsaFromFile); verifier.SetHashAlgorithm("SHA1"); return dsaFromFile.VerifySignature(rgbHash, rgbSignature); } catch (CryptographicException e) { return false; } catch (FormatException e) {
10
} }
return false;
////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // Sign an XML file. // This document cannot be verified unless the verifying // code has the key with which it was signed. public static void SignXml(XmlDocument Doc, RSA Key) { // Check arguments. if (Doc == null) throw new ArgumentException("Doc"); if (Key == null) throw new ArgumentException("Key"); // Create a SignedXml object. SignedXml signedXml = new SignedXml(Doc); // Add the key to the SignedXml document. signedXml.SigningKey = Key; // Create a reference to be signed. Reference reference = new Reference(); reference.Uri = ""; // Add an enveloped transformation to the reference. XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(env); // Add the reference to the SignedXml object. signedXml.AddReference(reference); // Compute the signature. signedXml.ComputeSignature(); // Get the XML representation of the signature and save // it to an XmlElement object. XmlElement xmlDigitalSignature = signedXml.GetXml(); // Append the element to the XML document. Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignatur } // Verify the signature of an XML file against an asymmetric // algorithm and return the result. public static Boolean VerifyXml(XmlDocument Doc, RSA Key) { // Check arguments. if (Doc == null) throw new ArgumentException("Doc"); if (Key == null) throw new ArgumentException("Key"); // Create a new SignedXml object and pass it // the XML document class.
e, true));
11
SignedXml signedXml = new SignedXml(Doc); // Find the "Signature" node and create a new // XmlNodeList object. XmlNodeList nodeList = Doc.GetElementsByTagName("Signature"); // Throw an exception if no signature was found. if (nodeList.Count <= 0) { throw new CryptographicException("Verification failed: No Signature was found in the document."); } // // // if { This example only supports one signature for the entire XML document. Throw an exception if more than one signature was found. (nodeList.Count >= 2)
throw new CryptographicException("Verification failed: More that one signature was found for the document."); } // Load the first <signature> node. signedXml.LoadXml((XmlElement)nodeList[0]); // Check the signature and return the result. return signedXml.CheckSignature(Key);
////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// } } Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Security.Cryptography; using System.Xml; using System.Security.Cryptography.Xml;
12
{ public Form1() { InitializeComponent(); } private void btnSignFile_Click(object sender, EventArgs e) { DSACryptoServiceProvider DSA = new DSACryptoServiceProvider(); byte[] FileToBeDSA = File.ReadAllBytes(txtPathToSignFile.Text); byte[] Hash = Helpers.Helpers.ComputeHash(FileToBeDSA); byte[] Signature = Helpers.Helpers.DSASignFile(Hash, DSA.ExportParameters(true), "SHA1"); Helpers.Helpers.ExportSignatureToFile(Signature, txtPathToSavedKeySign.Text + "\\" + txtSignatureName.Text + ".data"); Helpers.Helpers.ExportPublicKeyToXml(DSA.ToXmlString(false), txtPathToSavedKeySign.Text + "\\" + txtPubKeyFileName.Text + ".xml"); MessageBox.Show("The file was successfully signed"); } private void btnOpenSignFile_Click(object sender, EventArgs e) { txtPathToSignFile.Text = SelectFile(); } private void btnSelectPathToSavedKeySign_Click(object sender, EventArgs e) { DialogResult result = folderBrowserDialogSign.ShowDialog(); if (result == DialogResult.OK) { txtPathToSavedKeySign.Text = folderBrowserDialogSign.SelectedPath; }
13
} private string SelectFile() { Stream myStream = null; OpenFileDialog openFileDialogSign = new OpenFileDialog(); openFileDialogSign.InitialDirectory = "c:\\"; openFileDialogSign.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*"; openFileDialogSign.FilterIndex = 2; openFileDialogSign.RestoreDirectory = true; if (openFileDialogSign.ShowDialog() == DialogResult.OK) { try { if ((myStream = openFileDialogSign.OpenFile()) != null) { return openFileDialogSign.FileName; } } catch (Exception ex) { MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); } } return null; } private void btnOpenVerifiedFile_Click(object sender, EventArgs e) { txtPathToVerifiedFile.Text = SelectFile(); } private void btnSelectPathToPublicKey_Click(object sender, EventArgs e) { txtPathToPublicKey.Text = SelectFile(); }
14
private void btnSelectPathToSignature_Click(object sender, EventArgs e) { txtPathToSignature.Text = SelectFile(); } private void btnVerifyFile_Click(object sender, EventArgs e) { string publicXMLKeyFromFile = Helpers.Helpers.ImportPublicKeyFromXml(txtPathToPublicKey.Text); byte[] FileToBeVerified = File.ReadAllBytes(txtPathToVerifiedFile.Text); byte[] Signature = File.ReadAllBytes(txtPathToSignature.Text); byte[] Hash = Helpers.Helpers.ComputeHash(FileToBeVerified); bool status = Helpers.Helpers.DSAVerifyFile(publicXMLKeyFromFile, Hash, Signature); if (status) MessageBox.Show("The file was successfully verified"); else MessageBox.Show("The provided signature is invalid."); } ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// private void btnOpenSignXML_Click(object sender, EventArgs e) { txtPathToSignXML.Text = SelectFile(); } private void btnSignXML_Click(object sender, EventArgs e) { try { // Create a new CspParameters object to specify // a key container.
15
CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"; // Create a new RSA signing key and save it in the container. RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams); // Create a new XML document. XmlDocument xmlDoc = new XmlDocument(); // Load an XML file into the XmlDocument object. xmlDoc.PreserveWhitespace = true; xmlDoc.Load(txtPathToSignXML.Text); // Sign the XML document. Helpers.Helpers.SignXml(xmlDoc, rsaKey); MessageBox.Show("XML file signed."); // Save the document. xmlDoc.Save(txtPathToSignXML.Text);
} catch (Exception error) { MessageBox.Show(error.ToString()); } } private void btnOpenVerifiedXML_Click(object sender, EventArgs e) { txtPathToVerifiedXML.Text = SelectFile(); } private void btnVerifyXML_Click(object sender, EventArgs e) { try { // Create a new CspParameters object to specify
16
// a key container. CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"; // Create a new RSA signing key and save it in the container. RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams); // Create a new XML document. XmlDocument xmlDoc = new XmlDocument(); // Load an XML file into the XmlDocument object. xmlDoc.PreserveWhitespace = true; xmlDoc.Load(txtPathToVerifiedXML.Text); // Verify the signature of the signed XML. Console.WriteLine("Verifying signature..."); bool result = Helpers.Helpers.VerifyXml(xmlDoc, rsaKey); // Display the results of the signature verification to // the console. if (result) { MessageBox.Show("The XML signature is valid."); } else { MessageBox.Show("The XML signature is not valid."); } } catch (Exception error) { MessageBox.Show(error.Message); } } ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
17
} }
18