馬上就要過年回村裡了,村裡沒有wifi,沒有4G,沒有流量,更加重要的是過幾天電腦就得賣掉換車票了,得趕緊寫幾篇博客。
public byte[] SignData(Stream inputStream, object halg)
{
int calgHash = Utils.ObjToAlgId(halg, OidGroup.HashAlgorithm);
return this.SignHash(Utils.ObjToHashAlgorithm(halg).ComputeHash(inputStream), calgHash);
}
該方法存在三個重載方法,三個重載方法的第一個參數不同,分別是Stream、byte[]兩個類型。由代碼可以看出,該方法接受兩個參數,inputStream是要計算其哈希值的輸入數據,halg用於創建哈希值的哈希算法。SignHash()通過用私鑰對其進行加密來計算指定哈希值的簽名。
(2).VerifyData():通過使用提供的公鑰確定簽名中的哈希值並將其與所提供數據的哈希值進行比較驗證數字簽名是否有效。
public bool VerifyData(byte[] buffer, object halg, byte[] signature)
{
int calgHash = Utils.ObjToAlgId(halg, OidGroup.HashAlgorithm);
return this.VerifyHash(Utils.ObjToHashAlgorithm(halg).ComputeHash(buffer), calgHash, signature);
}
該方法沒有重載版本,有源碼可以看出該方法接收三個參數,分別是:buffer已簽名的數據,halg用於創建數據的哈希值的哈希算法名稱,signature要驗證的簽名數據。該方法返回一個布爾類型,如果簽名有效,則為 true;否則為 false。VerifyHash()通過使用提供的公鑰確定簽名中的哈希值並將其與提供的哈希值進行比較來驗證數字簽名是否有效。
2.DSA類解析:
(1).CreateSignature():創建指定數據的 Cryptography.DSA 簽名。
public abstract byte[] CreateSignature(byte[] rgbHash);
該方法為一個抽象方法,在派生類中重寫,接受一個字節數組表示要簽名的數據,返回指定數據的數字簽名。在使用CreateSignature方法時,必須自己創建SHA-1散列碼,返回一個用字節數組表示的DSA簽名。
(2).VerifySignature():驗證指定數據的 Cryptography.DSA 簽名。
public abstract bool VerifySignature(byte[] rgbHash, byte[] rgbSignature);
該方法接受字符數組表示的SHA-1散列碼和簽名來驗證。
3.DSACryptoServiceProvider類解析:
(1).ImportParameters():導入指定的 DSAParameters。該方法接受一個參數,Cryptography.DSA的參數。
(2).VerifyData():通過將指定的簽名數據與為指定數據計算的簽名進行比較來驗證指定的簽名數據。
public bool VerifyData(byte[] rgbData, byte[] rgbSignature)
{
return this.VerifyHash(this._sha1.ComputeHash(rgbData), (string) null, rgbSignature);
}
該方法接受兩個參數,rgbData已簽名的數據;rgbSignature要驗證的簽名數據,如果簽名驗證為有效,則為 true;否則,為 false。VerifyHash()通過將指定的簽名數據與為指定哈希值計算的簽名進行比較來驗證指定的簽名數據,我們看一下VerifyHash()的實現代碼:
public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature)
{
if (rgbHash == null)
throw new ArgumentNullException("rgbHash");
if (rgbSignature == null)
throw new ArgumentNullException("rgbSignature");
int calgHash = X509Utils.NameOrOidToAlgId(str, OidGroup.HashAlgorithm);
if (rgbHash.Length != this._sha1.HashSize / 8)
{
string key = "Cryptography_InvalidHashSize";
object[] objArray = new object[2];
int index1 = 0;
string str1 = "SHA1";
objArray[index1] = (object) str1;
int index2 = 1;
// ISSUE: variable of a boxed type
__Boxed<int> local = (ValueType) (this._sha1.HashSize / 8);
objArray[index2] = (object) local;
throw new CryptographicException(Environment.GetResourceString(key, objArray));
}
this.GetKeyPair();
return Utils.VerifySign(this._safeKeyHandle, 8704, calgHash, rgbHash, rgbSignature);
}
該方法接收三個參數,rgbHash要簽名的數據的哈希值,str用於創建數據的哈希值的哈希算法名稱,rgbSignature要驗證的簽名數據。
該類在System.Security.Cryptography.X509Certificates空間下,提供幫助你使用 X.509 v.3 證書的方法。
(1).LoadCertificateFromBlob():加載證書:
private void LoadCertificateFromBlob(byte[] rawData, object password, X509KeyStorageFlags keyStorageFlags)
{
if (rawData == null || rawData.Length == 0)
throw new ArgumentException(Environment.GetResourceString("Arg_EmptyOrNullArray"), "rawData");
if (X509Utils.MapContentType(X509Utils._QueryCertBlobType(rawData)) == X509ContentType.Pfx && (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) == X509KeyStorageFlags.PersistKeySet)
new KeyContainerPermission(KeyContainerPermissionFlags.Create).Demand();
uint dwFlags = X509Utils.MapKeyStorageFlags(keyStorageFlags);
IntPtr num = IntPtr.Zero;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
num = X509Utils.PasswordToHGlobalUni(password);
X509Utils._LoadCertFromBlob(rawData, num, dwFlags, (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) != X509KeyStorageFlags.DefaultKeySet, ref this.m_safeCertContext);
}
finally
{
if (num != IntPtr.Zero)
Marshal.ZeroFreeGlobalAllocUnicode(num);
}
}
該方法是X509Certificate類構造函數等幾個方法加載證書的具體實現方法。
(2).Export():使用指定的格式和密碼將當前 X509Certificate對象導出到字節數組。
public virtual byte[] Export(X509ContentType contentType, SecureString password)
{
return this.ExportHelper(contentType, (object) password);
}
該方法接受兩個參數,contentType描述如何設置輸出數據格式的 X509ContentType 值之一。password訪問 X.509 證書數據所需的密碼。返回表示當前 X509Certificate 對象的字節數組。
下面提供一個X509Certificate的操作方法實例:
public void EncryptXmlDocument(string arqXmlAssinar, string tagAssinatura, string tagAtributoId, X509Certificate2 x509Cert)
{
StreamReader sr = null;
try
{
sr = System.IO.File.OpenText(arqXmlAssinar);
var xmlString = sr.ReadToEnd();
sr.Close();
sr = null;
XmlDocument doc = new XmlDocument { PreserveWhitespace = false };
doc.LoadXml(xmlString);
if (doc.GetElementsByTagName(tagAssinatura).Count == 0)
{
throw new Exception(tagAssinatura.Trim());
}
if (doc.GetElementsByTagName(tagAtributoId).Count == 0)
{
throw new Exception(tagAtributoId.Trim());
}
XmlNodeList lists = doc.GetElementsByTagName(tagAssinatura);
foreach (XmlNode nodes in lists)
{
foreach (XmlNode childNodes in nodes.ChildNodes)
{
if (!childNodes.Name.Equals(tagAtributoId))
continue;
if (childNodes.NextSibling != null && childNodes.NextSibling.Name.Equals("Signature"))
continue;
Reference reference = new Reference { Uri = "" };
XmlElement childElemen = (XmlElement)childNodes;
if (childElemen.GetAttributeNode("Id") != null)
{
var attributeNode = childElemen.GetAttributeNode("Id");
if (attributeNode != null)
reference.Uri = "#" + attributeNode.Value;
}
else if (childElemen.GetAttributeNode("id") != null)
{
var attributeNode = childElemen.GetAttributeNode("id");
if (attributeNode != null)
reference.Uri = "#" + attributeNode.Value;
}
XmlDocument documentoNovo = new XmlDocument();
documentoNovo.LoadXml(nodes.OuterXml);
SignedXml signedXml = new SignedXml(documentoNovo) { SigningKey = x509Cert.PrivateKey };
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
XmlDsigC14NTransform c14 = new XmlDsigC14NTransform();
reference.AddTransform(c14);
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(x509Cert));
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature();
XmlElement xmlDigitalSignature = signedXml.GetXml();
nodes.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
}
}
var xmlDoc = doc;
var stringXmlAssinado = xmlDoc.OuterXml;
StreamWriter sw2 = System.IO.File.CreateText(arqXmlAssinar);
sw2.Write(stringXmlAssinado);
sw2.Close();
}
catch (CryptographicException ex)
{
throw new CryptographicException(ex.Message);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
finally
{
if (sr != null) sr.Close();
}
}
上面是有關.NET數字證書的簡單介紹,如有寫的不對的地方還望多多見諒,在博文中有些類和方法沒有較多的列舉出來,有興趣的可以自己去深入的了解。我們學習一個知識時,已經從知識的結構了解開始,這樣有利於我們站在全局思考問題。