Hello Everyone,
First, I'd like to thank
Mehdi Gholam for sharing his insights with me
and with the rest of the world on the matter pertaining to this topic. Thank you very much.
Mehdi Gholam is correct, the
signature value is appended to the X.509 certificate and that .Net abstracts the actual data of the signature itself and just validates it for us. The information provided on Wikipedia regarding X.509 certificates are very broad, but is good for those who want a brief explaination about X.509 certificates.
Anyway, X.509 certificates employ the
ASN.1 Distinguished Encoding Rule (DER) to structure its
binary format. So to understand the file structure of a X.509 certificate, one must learn the basics of
ASN.1. That is what I did. Here are the links.
RFC 2459
RFC 3280 (updated version of 2459)
Introduction to ASN.1
Wikipedia article on ASN.1
Wikipedia article on X.509 Suggested by Mehdi Gholam in his solution
Below is the definition of a X.509 certificate stated in RFC 3280. The syntax of the definition is in ASN.1.
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING }
In ASN.1, a
SEQUENCE is a data structure that encapsulates different data types. Here, Certificate is defined as a
SEQUENCE type using the ASN.1 operator (
::=). In ASN.1, a data type is defined by another data type. Furthermore, data structures and data types can be nested. In this case,
tbsCertificate is a data type defined as a
TBSCertificate type.
TBSCertificate itself is a
SEQUENCE type. This way of formulating a definition could somewhat be a little confusing at first. I recommend thinking in terms of "type-value" pairs. For example,
tbsCertificate can be viewed as a type having the value,
TBSCertificate.
Having said that and following this "type-value" perspective, we can see that
signatureAlgorithm has a value,
AlgorithmIdentifier, which is defined in RFC 3280 as a
SEQUENCE type that encapsulates an
OBJECT IDENTIFIER type and an
ANY type.
And once you've become comfortable with ASN.1, you would then be able to see the definitions as "type-data type" pairs. For example, the
signatureValue is a
BIT STRING type, which btw is where the actual
signature value is stored.
Below is an example of the decoded data that is appended to a X.509 certificate. In accordance to what I stated above, the
SEQUENCE here is
AlgorithmIdentifier and the
BIT STRING is the
signatureValue. The first integer from the left,
511, identifies the byte offset in the certificate file. The second integer is the
Tag Number, which serves as an identifier for a data type. For example,
0x30 is the
Tag Number for the
SEQUENCE type and
0x06 is the
Tag Number for the
OBJECT IDENTIFIER type. The third integer identifies the length of the data type. For example,
13 specifies that the length of
SEQUENCE is 13 bytes long. Finally the colon,
: , is just there to seperate the definition and from those numbers.
511 30 13: SEQUENCE {
513 06 9: OBJECT IDENTIFIER
: sha1withRSAEncryption (1 2 840 113549 1 1 5)
524 05 0: NULL
: }
526 03 129: BIT STRING 0 unused bits
: 1E 07 77 6E 66 B5 B6 B8 57 F0 03 DC 6F 77
: 6D AF 55 1D 74 E5 CE 36 81 FC 4B C5 F4 47
: 82 C4 0A 25 AA 8D D6 7D 3A 89 AB 44 34 39
: F6 BD 61 1A 78 85 7A B8 1E 92 A2 22 2F CE
: 07 1A 08 8E F1 46 03 59 36 4A CB 60 E6 03
: 40 01 5B 2A 44 D6 E4 7F EB 43 5E 74 0A E6
: E4 F9 3E E1 44 BE 1F E7 5F 5B 2C 41 8D 08
: BD 26 FE 6A A6 C3 2F B2 3B 41 12 6B C1 06
: 8A B8 4C 91 59 EB 2F 38 20 2A 67 74 20 0B
: 77 F3
: }
For
WindowsXP users, the "
certmgr.msc" utility
does not show the
signature value of a certificate, but rather a "
Thumbprint" value. This "Thumbprint" value is a digest(hash) of the
entire certificate(in ASN.1 DER binary format) itself.
It is dynamically generated and is not part of the X.509 certificate. The
signature value is a digest(hash) of the certificate as well,
but it is the digest(hash) of the
tbsCertificate type as defined in RFC 3280. Therefore, for those who are curious, the "Thumbprint" value
is not the "signature value" in it's decrypted form.
Regarding
.Net's RSA implementation, it uses a
public key for
encryption and a
private key for
decryption. The RSA decryption algorithm implementated in
RSACryptoServiceProvider.Decrypt() utilizes a
private key. This is by
design and thus, we
cannot use it to decrypt RSA encrypted data with a public key even if that data was encrypted with the corresponding private key. For those of us who are familiar with
Microsoft, this is
not the first time it has attempted to
control us by making us do things the way they "
think" it should be done.
Finally, thank you all for reading. If you happened to stumbled upon this post while searching for an answer to the same question that I had, then I hope this helped. Cryptography is a complicated subject; it has to be. Information about certain cryptographic algorithm or even the algorithm standard itself are either scattered, limited, unavailable, or incomprehensible. But do not let that discourage you from learning; I didn't.