2011年7月10日 星期日

Beginning with Digital Signatures in .NET Framework


This article explains how to get started with digital signatures, using X509 certificates in .NET.

The purpose of digital signatures is to identify data in a way that cannot easily be faked. Phishing, infected software and illegal contents published by unknown subjects can be prevented with digital signatures. Digital signatures will allow data and digital documents to be used as if they were signed paper. Browsers are now able to recognize X.509 certificates and know which Certificate Authorities are trusted. The X.509 system has grown to be the standard format for public key certificates, and is therefore the best way of proving that a document comes from the source it claims to come from.

This article will introduce X509 certificates, explain a little about the asymmetric cryptography that is at their heart, and end by describing how to use and manage these certificates within the .NET Framework classes.

Asymmetric Cryptography and Digital Signatures

Digital signatures are created using asymmetric cryptography, the approach on which digital signatures are based. Asymmetric Cryptography is distinguished by having two different keys, a private key to encrypt messages and a public key to decrypt them. The cryptographic private key K0 (a suitable array of bytes) is used with an appropriate algorithm to transform the initial human-readable message into a different message that is encrypted.

A second public cryptographic key K1, which is related to the private one, is used to change the encrypted message back to its original decrypted form via a second related algorithm.

With this mechanism, your recipient is sure that the message that she/he received is your message, because only you hold the private key that is related to the public, shared, key. You digitally ‘sign’ your message.

In practice, you will hash the message beforehand (with hash algorithm such as MD5 or SHA1), obtaining the hashed message M1. Then you will encrypt M1 with your private key K0, digitally signing your message, and, finally, you will send your message M, the encrypted hash M1 (the signature) and the public key K1 to your recipient. Your recipient will compute the hash of your message M and will compare it with the decrypted value of M1. If the two hashes matches, the signature is valid.

You will notice that the signature is obtained by encrypting the hash of a message, rather than the message itself. This is done for performance reasons. Asymmetric cryptography is a slow process and the time required to encrypt, or decrypt, a message is directly related to the message length. You can make better use of the processor by reducing the amount of data to be processed. Sometimes, a very large (in bytes) message, can be reduced, by hashing it, to a much smaller hashed message. It is more convenient to transmit a the bulk of the data as clear text and just attach less than a hundred encrypted bytes attached to it than to encrypt the entire message and send it in the encrypted form.

Asymmetric key encryption by itself is not enough because it is necessary to trust the public key received. An attacker can deceive you by signing a message with his private key and send you a digitally confirmed message with its (related) public key, whilst pretending he is someone else.

The public-key infrastructure (PKI) avoids this by utilizing a third-party entity, called Certification Authority that, under its responsibility, binds a public key to its owner. The binding occurs when the Certification Authority digitally sign a message that contains the public key and the identity of its owner. A digital certificate is obtained.

The X509 Standard for Digital Certificate

Today, the standard that has been adopted for digital certificate format is the X509 standard. Over the years since X.509 was developed in 1988, the initial X509 certificate format has evolved beyond the simple purpose of associating the identity of the subject with the public key, since it allows extended information to be held. The current certificate format is X509 v3 format, defined on RFC 5280. The most important information fields that it holds and stores is

  • Issuer: The identity of the certification authority that signed the certificate, validating it. It is expressed in ITU-T X.501 Distinguished Name format.
  • Validity: it defines the dates between which the certificate can be used.
  • Subject: it defines the identity of the public key owner. It is expressed as ITU-T X.501 Distinguished Name format.
  • SubjectPublicKeyInfo: it contains an encoded version of the public key.
  • X509 v3 extensions: it defines a set of extensions that establishes the purpose of the certificate and set some properties related to its management. Each extension can be critical (e.g. cannot be ignored) or not.

    Among the X509 v3 extensions, the two most important are

    • Key Usage: it defines the usage allowed for the private key, for example digitalSignature (allow the digital signature), keyCertSign (allow the signature of certificates by a certification authority), keyAgreement (allow the key exchange on protocol such as TLS/SSL).
    • Extended Key Usage: it defines extended properties in relation to the usage of the private key. For example Server Authentication (for TLS/SSL certificate), Code Signing (for authenticode signature), Email Protection (for protocol such as S/MIME).

You can view the certificates installed on a Windows® machine by using certmgr.msc

In the details tab, you can see the binding between the subject identity (Subject field) and the Public Key (Public Key field). This is highlighted to show its content. It consists of a sequence of bytes in hexadecimal form.

An important feature of the X509 standard is the assignment of a unique identifier to each entity inside a X509 certificate which is in the form of a sequence of numbers organized hierarchically; For example, the sequence 1.3.6.1.5.5.7.3.1 identifies the Server Authentication extended-key usage. Those sequences, called OIDs (object identifiers) are assigned by the authorized organization (IANA, ISO and ITU-T).

The most commonly used Certificate file format today is the PKCS#12 (personal information exchange standard) format. This standard permits you to prepare a X509 certificate file that may contain the private key as well, encrypted with a secret password. This is easiest imagined as a bag that contains the X509 certificate and the encrypted private key.

Manage X509 Certificates Stores with .NET Framework

The .NET classes involved on the X509 certificate management are those under the System.Security.Cryptography.X509Certificates namespace.

Before it can be used, a digital certificate must be located and loaded. X509 certificates are stored on Microsoft® Windows machines in a container that can be browsed with certmgr.msc command. Launching the command, you will see something like this:

This shows the so called “current user” certificate container, the container associated with the user currently logged on the machine. The “Personal” subfolder contains one certificate with a ‘friendly name’ given by webmail.

X509 certificates can be stored on a ‘per machine’ basis too. To open the certificate container for a local or remote machine, run mmc.exe and add the certificates snap-in, selecting the computer you want to administer.

Within the .NET Framework base classes, a subfolder is called “store”. A certificates store can be opened utilizing the X509Store class:

X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);

store.Open(OpenFlags.OpenExistingOnly);

In this example, the “current user” container is opened and the certificates that reside on the “Personal” store are loaded.

To open a store on the “local machine” container, you must change the StoreLocation enumeration value with the value:

StoreLocation.LocalMachine

The store that you wish to open is set with the StoreName enumeration. Others enumeration values allow you to select other stores inside the container. These are stores related to the X509 certificates that are issued to other entities involved in the PKI system. Those are beyond the scope of this article.

Notice now the Open method. This accepts, as an input parameter, an OpenFlags enumeration value given by OpenExistingOnly. This states that the Open method can only open an existing store inside the container. It might seem to imply to you that stores can be created too. And you’d be right. Using the appropriate override of theX509Store class constructor, a new store can be created:

X509Store store = new X509Store(“MyStore”, StoreLocation.CurrentUser);

store.Open(OpenFlags.ReadWrite);

In this example, a new store named “MyStore” is created and opened for read write operations.

Notice that, if a new store is created, the .NET Framework doesn’t allow you to remove it anymore. There is no method that permits a store deletion. It can be deleted only with another tool such as CAPICOM or by using Microsoft® CryptoAPI directly.

It’s time now to work with certificates on the stores. To do so, the X509Store class provides a Certificates property of type X509Certificate2Collection:

X509Certificate2Collection certificates = store.Certificates;

The certificates object now contains all the certificates stored on the opened store. A certificate can be retrieved from the collection with the following code:

X509Certificate2 certificate = certificates[n];

with n being the selected index.

A certificate can also be loaded from a certificate file:

X509Certificate2 myCertificate = new X509Certificate2(“c:\....\mycertificate.pfx”);

and then saved into the opened store:

store.Add(myCertificate);

Finally, a certificate can be removed from a store with the method:

store.Remove(certificates[n]);

Manage X509 Certificates with .NET Framework

The X509Certificate2 class allows you to manage the “certificate data units” programmatically. First of all, notice the suffix 2 on the class name. This happens because the X509Certificate2 class extends methods and properties of its base class, the X509Certificate class. It extends the X509Certificate class by allowing, above all, the management of the private key (if present, as seen for the PKCS#12 certificate format), and the browsing of the X509 v3 extensions.

The X509Certificate2 class allows you to retrieve, from the certificate that is loaded, its representative data through a set of properties. Among them:

Name

Type

Description

Issuer

string

Identify the issuer of the certificate (the certification authority that signed the certificate).

Subject

string

Identify the subject, owner of the private key.

NotBefore

DateTime

It states that the certificate can be used only after the NotBefore data.

NotAfter

DateTime

It states that the certificate can be used until the NotAfter data.

PublicKey

PublicKey

Represents the Public Key associated to the subject.

Extensions

X509ExtensionCollection

Collection of X509 v3 extensions.

In those, the public key is retrieved as a PublicKey object. This object contains all the information related to the public key itself, but this information are not easy to explain in this article because the reader would require a knowledge of asymmetric cryptographic algorithms, ASN.1 encoding rules and OID assignment.

You can however get a string representation of the public hey by utilizing a X509Certificate class method, from which X509CertificateClass2 derives:

string publicKey = certificate.GetPublicKeyString();

The publicKey string now contains the same string representation of the public key seen on the first image proposed on this article (without white spaces).

The X509 v3 Extensions can be analyzed through browsing on the collection elements. Those are of type X509Extension. This type defines the OID assigned to the related extension and its ASN.1 encoded value.

Performing Signatures with the .NET Framework

To perform a signature using an X509 certificate and .NET Framework base classes, the X509 certificate must have the private key too. In fact, as stated previously, a signature consists of an encryption with the private key (that must be present) of hashes computed on messages to sign. If an object of type X509Certificate2 has the private key (due to the fact that the PKCS#12 file imported on the store has the private key). This can be retrieved with the following code:

AsymmetricAlgorithm privateKey = certificate.PrivateKey;

You'll have noticed the type of PrivateKey property. It is of type AsymmetricAlgorithm, a class that can be found under the System.Security.Cryptography namespace. Is seems to have nothing to do with private keys. But remember that the private key is an element, inside the PKI elements, that require an high level of protection. When importing a PKCS#12 file into your X509 store, the private key became a more complex “object” inside the store, in the sense that it is saved “keeping in mind the purpose of the same and its protection requirements”. It need an unique identifier to search for it, it need protection against attacker, it need access control, it need a suitable, but flexible, storage. Without entering more deeply on the argument, think of this object as a sort of “pipeline” between your code and the cryptographic subsystem of your operating system that manages, in a secure way, all the cryptographic operation based on your key pairs.

In reality, the AsymmetricAlgorithm class is only a base class of more complex classes. It is the base class for all the classes that implement specific asymmetric algorithms standards. Today, a widely-adopted standard for digital signature is RSA asymmetric encryption with SHA-1 hash algorithm. If the certificate contains RSA asymmetric keys pairs, the previous method does not, as one might expect, return an AsymmetricAlgorithm object, but an RSACryptoServiceProvider object, whose class derives from the AsymmetricAlgorithm class. The RSACryptoServiceProvider class contains all the properties and methods that are related to what we said previously.

So, the next step is to cast the privateKey object to a RSACryptoServiceProvider object, or, in more elegant way:

RSACryptoServiceProvider privateKey

= certificate.PrivateKey as RSACryptoServiceProvider;

Now a signature can be performed. To do so, the SignData method of the privateKey object can be used. It accepts, as input, (1) the data to sign, as array of bytes, and (2) the object that represents the hash algorithm to use:

byte[] buffer = Encoding.Default.GetBytes("Hello World ... !");

byte[] signature = privateKey.SignData(buffer, new SHA1Managed());

The signature can also be verified. To do so you must utilize the public key of the certificate.

RSACryptoServiceProvider publicKey

= certificate.PublicKey.Key as RSACryptoServiceProvider;

bool verify = publicKey.VerifyData

(buffer, new SHA1Managed(), signature);

From the above example you see that the certificate.PublicKey.Key property is again an object of type AsymmetricAlgortihm. This is for the same reasons seen for the private key.

The certificate to use for the verification can be the same certificate used for the generation of the signature but even a version of it that contains only the public key. No private key is required. And this is what always happens. Remember that the recipient receive only the signed message plus the certificate without the private key, that remain secret and accessible only by its owner. This means that verifications occurs always with the utilization of the public key “extracted” from a certificate that doesn’t have private key.

Another way to perform signature is to use the class RSAPKCS1SignatureFormatter. It brings to the same result of the previous method. To do so, the hash of data to sign must be computed first:

byte[] buffer = Encoding.Default.GetBytes("Hello World ... !");

byte[] hash = SHA1Managed.Create().ComputeHash(buffer);

RSAPKCS1SignatureFormatter formatter

= new RSAPKCS1SignatureFormatter(certificate.PrivateKey);

formatter.SetHashAlgorithm("SHA1");

signature = formatter.CreateSignature(hash);

To verify the signature, use the RSAPKCS1SignatureDeformatter class:

RSAPKCS1SignatureDeformatter deformatter

= new RSAPKCS1SignatureFormatter(certificate.PublicKey.Key);

deformatter.SetHashAlgorithm("SHA1");

bool verify = formatter.VerifySignature(hash,signature);

Conclusion

This article gave an outline of what a digital signature is, and how to digitally sign data with the .NET Framework. Digital signatures, and cryptographic services in general, are very complex subjects and are not easy to summarize. If you feel we haven't really helped to make it clearer for you, please say so by leaving a comment to this article and even ask the author for other articles on the subject, indicating what you would like to read more about.

If you would like to experiment digital signatures with X509 certificate, probably you need some X509 certificate for testing. We end this paper by providing you some way to gets digital certificates:

  • You can download the openssl projects files at The OpenSSL Project and set up a smart certification authority.

  • You can use makecert.exe command (see Certificate Creation Tool (Makecert.exe) ) that you can find on Microsoft® Windows SDK.

  • You can generate X509 certificate on-line using X509 Builder web application at the author’s site wecoffee.

source: http://www.simple-talk.com/content/print.aspx?article=833

2011年7月7日 星期四

x509,pkcs7和Pkcs12之間關係


x.509,是x500那套網絡協議(好像是目錄協議吧)的一個子集,專門定義了在目錄訪問中需要身份認證的證書的格式。後來被rfc收錄3280。

PKCS#12是“個人信息交換語法”。它可以用來將x.509的證書和證書對應的私鑰打包,進行交換。比如你在windows下,可以將IE裡的證書連帶私鑰導出,並設置一個口令保護。這個pfx格式的文件,就是按照pkcs#12的格式打包的。當然pkcs#12不僅僅只是作以上用途的。它可以用來打包交換任何信息。你可以和張三李四用PKCS#12來交換私人數據,包括x.509證書和私鑰。
你在交換x.509證書和私鑰可以採用任何數據格式,例如PKCS#12。

PKCS#7麼,舉個例子,你給張三李四發了一封籤名郵件,同時你將你的個人證書隨郵件一起發給了張三李四,這個時候,你可以按照PKCS#7的格式來打包。

P7一般是把證書分成兩個文件,一個公鑰一個私鑰,有PEM和DER兩種編碼方式。PEM比較多見,就是純文本的,P7一般是分發公鑰用,看到的就是一串可見字符串,擴展名經常是.crt,.cer,.key等。 DER是二進制編碼。
P12是把證書壓成一個文件,.pfx 。主要是考慮分發證書,私鑰是要絕對保密的,不能隨便以文本方式散播。所以P7格式不適合分發。 .pfx中可以加密碼保護,所以相對安全些。
在實踐中要中,用戶證書都是放在USB Key中分發,服務器證書經常還是以文件方式分發。服務器證書和用戶證書,都是X509證書,就是裡面的屬性有區別.


X509 是證書規範
PKCS#7 是消息語法(常用於數字簽名與加密)
PKCS#12 個人消息交換與打包語法(如.PFX .P12)打包成帶公鑰與私鑰
還有其它常用的是PKCS#10 是證書請求語法。

通過CA產生的出來的證書格式文件一般是以PFX P12格式發布給使用者(公鑰與私鑰),用戶拿到證書後,
可以通過IE來導入或直接雙擊嚮導安裝證書,此時私鑰安裝到系統的私有密鑰庫中。使用時系統會自動查找到
私鑰。而最安全的方式還是使用其它USB硬件來存儲,私鑰將無法再從硬件鎖只導出,並且支持硬件訪問需要
用戶的密鑰才能訪問到硬件內的私鑰,永遠保證了私鑰不出硬件鎖!提高了安全性,靈活性,且可以移動的方便性。如ETOKEN產品,一些硬件信息可參考www.dztech.cn.
而相互雙方通迅時使用且​​交換的是帶公鑰的證書如CER文件。




PKI標準可以分為第一代和第二代標準[12]。

第一代PKI標準主要包括美國RSA公司的公鑰加密標準(Public Key Cryptography Standards,PKCS)系列、國際電信聯盟的ITU-T X.509、IETF組織的公鑰基礎設施X.509(Public Key Infrastructure X .509,PKIX)標準系列、無線應用協議(Wireless Application Protocol ,WAP)論壇的無線公鑰基礎設施(Wireless Public Key Infrastructure,WPKI)標準等。第一代PKI標準主要是基於抽象語法符號(Abstract Syntax Notation One,ASN.1)編碼的,實現比較困難,這也在一定程度上影響了標準的推廣。
第二代PKI標準是在2001年,由微軟、VeriSign和webMethods三家公司發布了XML密鑰管理規範(XML Key Management Specification,XKMS),被稱為第二代PKI標準。 XKMS由兩部分組成:XML密鑰信息服務規範(XML Key Information Service Specification,X-KISS)和XML密鑰註冊服務規範(XML Key Registration Service Specification,X-KRSS)。 X-KISS定義了包含在XML-SIG元素中的用於驗證公鑰信息合法性的信任服務規範;使用X-KISS規範,XML應用程序可通過網絡委託可信的第三方CA處理有關認證簽名、查詢、驗證、綁定公鑰信息等服務。 X-KRSS則定義了一種可通過網絡接受公鑰註冊、撤銷、恢復的服務規範;XML應用程序建立的密鑰對,可通過X-KRSS規範將公鑰部分及其它有關的身份信息發給可信的第三方CA註冊。 X-KISS和X-KRSS規範都按照XML Schema 結構化語言定義,使用簡單對象訪問協議(SOAP V1.1)進行通信,其服務與消息的語法定義遵循Web服務定義語言(WSDL V1.0)。目前XKMS已成為W3C的推薦標準,並已被微軟、VeriSign等公司集成於他們的產品中(微軟已在ASP.net中集成了XKMS,VeriSign已發布了基於Java的信任服務集成工具包TSIK)。
CA中心普遍採用的規範是X.509[13]系列和PKCS系列,其中主要應用到了以下規範:
1. X.209(1988)
ASN.1是描述在網絡上傳輸信息格式的標準方法。它有兩部分:第一部份(ISO 8824/ITU X.208)描述信息內的數據、數據類型及序列格式,也就是數據的語法;第二部分(ISO 8825/ITU X.209)描述如何將各部分數據組成消息,也就是數據的基本編碼規則。
ASN.1原來是作為X.409的一部分而開發的,後來才獨立地成為一個標準。這兩個協議除了在PKI體系中被應用外,還被廣泛應用於通信和計算機的其他領域。
2. X.500(1993)
X.500是一套已經被國際標準化組織(ISO)接受的目錄服務系統標準,它定義了一個機構如何在全局範圍內共享其名字和與之相關的對象。 X.500是層次性的,其中的管理域(機構、分支、部門和工作組)可以提供這些域內的用戶和資源信息。在PKI體系中,X.500被用來惟一標識一個實體,該實體可以是機構、組織、個人或一台服務器。 X.500被認為是實現目錄服務的最佳途徑,但X.​​500的實現需要較大的投資,並且比其他方式速度慢;而其優勢具有信息模型、多功能和開放性。
3. X.509(1993)
X.509是由國際電信聯盟(ITU-T)制定的數字證書標準。在X.500確保用戶名稱惟一性的基礎上,X.509為X.500用戶名稱提供了通信實體的鑑別機制,並規定了實體鑑別過程中廣泛適用的證書語法和數據接口。
X.509的最初版本公佈於1988年。 X.509證書由用戶公共密鑰和用戶標識符組成。此外還包括版本號、證書序列號、CA標識符、簽名算法標識、簽發者名稱、證書有效期等信息。這一標準的最新版本是X.509 v3,它定義了包含擴展信息的數字證書。該版數字證書提供了一個擴展信息字段,用來提供更多的靈活性及特殊應用環境下所需的信息傳送。
4. PKCS系列標準
PKCS是由美國RSA數據安全公司及其合作夥伴制定的一組公鑰密碼學標準,其中包括證書申請、證書更新、證書作廢表發布、擴展證書內容以及數字簽名、數字信封的格式等方面的一系列相關協議。到1999年底,PKCS已經公佈了以下標準:
PKCS#1:定義RSA公開密鑰算法加密和簽名機制,主要用於組織PKCS#7中所描述的數字簽名和數字信封。
PKCS#3:定義Diffie-Hellman密鑰交換協議。
PKCS#5:描述一種利用從口令派生出來的安全密鑰加密字符串的方法。使用MD2或MD5 從口令中派生密鑰,並採用DES-CBC模式加密。主要用於加密從一個計算機傳送到另一個計算機的私人密鑰,不能用於加密消息。
PKCS#6:描述了公鑰證書的標準語法,主要描述X.509證書的擴展格式。
PKCS#7:定義一種通用的消息語法,包括數字簽名和加密等用於增強的加密機制,PKCS#7與PEM兼容,所以不需其他密碼操作,就可以將加密的消息轉換成PEM消息。
PKCS#8:描述私有密鑰信息格式,該信息包括公開密鑰算法的私有密鑰以及可選的屬性集等。
PKCS#9:定義一些用於PKCS#6證書擴展、PKCS#7數字簽名和PKCS#8私鑰加密信息的屬性類型。
PKCS#10:描述證書請求語法。
PKCS#11:稱為Cyptoki,定義了一套獨立於技術的程序設計接口,用於智能卡和PCMCIA卡之類的加密設備。
PKCS#12:描述個人信息交換語法標準。描述了將用戶公鑰、私鑰、證書和其他相關信息打包的語法。
PKCS#13:橢圓曲線密碼體制標準。
PKCS#14:偽隨機數生成標準。
PKCS#15:密碼令牌信息格式標準。
5. OCSP在線證書狀態協議
OCSP(Online Certificate Status Protocol)[14]是IETF頒布的用於檢查數字證書在某一交易時刻是否仍然有效的標準。該標準提供給PKI用戶一條方便快捷的數字證書狀態查詢通道,使PKI體系能夠更有效、更安全地在各個領域中被廣泛應用。
6. LDAP 輕量級目錄訪問協議
LDAP規範(RFC1487)簡化了笨重的X.500目錄訪問協議,並且在功能性、數據表示、編碼和傳輸方面都進行了相應的修改。 1997年,LDAP第3版本成為互聯網標準。目前,LDAP v3已經在PKI體系中被廣泛應用於證書信息發布、CRL信息發布、CA政策以及與信息發布相關的各個方面。


source: