Home All Groups Group Topic Archive Search About

Bug in X509Certificate.GetSerialNumber and X509Certificate.GetSerialNumberString

Author
23 Feb 2005 7:35 AM
John Allberg

Hi!

There is a bug i X509Certificate.GetSerialNumber and
X509Certificate.GetSerialNumberString where the serialnumber bytes is in the
reverse order.

Example:
Open a verisign certificate. Verisign certificates have very long
serialnumbers, since they are generated from a hash value.

For my verisign certificate:
X509Certificate.GetSerialNumberString returns
FC67A62CBA193D0198061E48E65B8457

GetSerialNumber returns the same, even though it is in bytes.

When opening the certificate in explorer and looking at the serialnumber
field:
57 84 5b e6 48 1e 06 98 01 3d 19 ba 2c a6 67 fc

When parsing the certificate in an asn1 browser:
   0 30  869: SEQUENCE {
   4 30  718:   SEQUENCE {
   8 A0    3:     [0] {
  10 02    1:       INTEGER 2
            :       }
  13 02   16:     INTEGER
            :       57 84 5B E6 48 1E 06 98 01 3D 19 BA 2C A6 67 FC


When looking in Verisign admin tools, it is reported as
57845be6481e0698013d19ba2ca667fc

As you can see, this is the reverse of what X509Certificate.GetSerialNumber
reports. I'd say this is a bug.

Regards,

John Allberg
PS. This is a post using MSDN MSDN Managed Newsgroups with a registered MSDN
nospam mail account. It never worked for me before, but hey, sometime is
going to be the first, right? DS.

Author
23 Feb 2005 9:31 AM
Peter Huang" [MSFT]
Hi

Based on my research, I think this is the different order about how  win32
explorer and .NET framework handle the serial number byte array.
I have tried to open a test certificate and I find that the certificate's
byte array order is same as the output of .net's GetSerialNumber method. It
seems that the explorer has done the reverse job in advance. Based on my
knowlege, the serial number is used to identify the certificate which is
similar with GUID, so usually we use it to compare if two cert is identity.
So in the .net world, we do not need to do the reverse job.

While if you want to show the serialnumber same with the explorer.
We can just do the reserver job in .net as below.

// The path to the certificate.
string Certificate =  @"c:\test.cer";
// Load the certificate into an X509Certificate object.
X509Certificate cert = X509Certificate.CreateFromCertFile(Certificate);
// Get the value.
byte[] results = cert.GetSerialNumber();
Array.Reverse(results);
// Display the value to the console.
foreach(byte b in results)
{
    Console.Write("{0:x} ",b);
}
Console.WriteLine();

If you still have any concern, please feel free to post here.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
Are all your drivers up to date? click for free checkup

Author
25 Feb 2005 3:05 PM
John Allberg
Hi Peter!

Thank you for your swift response.

I have to disagree with you though... ;-) Please note that I'm using
certificates with very long (16 bytes) serialnumbers.

If I open my test certificate with a asn1 viewer, for example asn1guidump
http://www.geminisecurity.com/guidumpasn.html, this it what I see:
   0 30  869: SEQUENCE {
   4 30  718:   SEQUENCE {
   8 A0    3:     [0] {
  10 02    1:       INTEGER 2
            :       }
  13 02   16:     INTEGER
            :       57 84 5B E6 48 1E 06 98 01 3D 19 BA 2C A6 67 FC
<snip>

The first integer is the X509 version nr, saying that this is a x509v3
certificate.
The next integer is the certificate serial number. That's the bytes I'd
expect to get when calling getSerialNumber.

If I do a binary dump of the certificate:
30 82 03 65 = SEQUENCE
30 82 02 ce = SEQUENCE
    a0 03 = [0]
        02 01 02  = INTEGER 2
        02 10 57 84 5b e6 48 1e 06 98 01 3d 19 ba 2c a6 67 fc = INTEGER,
0x10 bytes long, value is 57845b and so on
<snip>
As you can see, this perfectly matches with the asn1 dump above.

When I simply doubleclick on the certificate file, at least with my
configuration (Win XP SP2), it displays certificate serialnumber 57 84 5b e6
48 1e 06 98 01 3d 19 ba 2c a6 67 fc. What config were you using when you
opened the
certificate and saw the reverse?

I have access to the Verisign Control Center, where I for example can revoke
the certificate, where the serialnumber is displayed as
57845be6481e0698013d19ba2ca667fc.

So, to sum it all up:
..Net:     FC 67 A6 2C BA 19 3D 01 98 06 1E 48 E6 5B 84 57
Asn1dump: 57 84 5B E6 48 1E 06 98 01 3D 19 BA 2C A6 67 FC
Binary:   57 84 5B E6 48 1E 06 98 01 3D 19 BA 2C A6 67 FC
Explorer: 57 84 5B E6 48 1E 06 98 01 3D 19 BA 2C A6 67 FC
VSGN CC:  57 84 5B E6 48 1E 06 98 01 3D 19 BA 2C A6 67 FC

I still think this is a bug in .Net Framework. By the way, I'm using v1.1.

Thank you for your example how to reverse the bytes. I have implemented
something similar. I thought that this is a bug, so I wanted to report it to
Microsoft so they/you are able to fix it to the next release (2.0?).

Regards,

John Allberg

My testcertificate:
-----BEGIN CERTIFICATE-----
MIIDZTCCAs6gAwIBAgIQV4Rb5kgeBpgBPRm6LKZn/DANBgkqhkiG9w0BAQQFADCB
hzEfMB0GA1UEChMWVGVsaWFTb25lcmEgU3ZlcmlnZSBBQjEeMBwGA1UECxMVRm9y
IHRlc3QgcHVycG9zZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
b3JrMSMwIQYDVQQDExpUZWxpYVNvbmVyYSBTL01JTUUgVEVTVCBDQTAeFw0wNTAy
MjMwMDAwMDBaFw0wNjAyMjMyMzU5NTlaMIGFMRQwEgYDVQQKDAtUZWxpYVNvbmVy
YTEUMBIGA1UECwwLVGVzdCBTL01JTUUxIDAeBgNVBAsMF3d3dy50cnVzdC50ZWxp
YS5jb20vcnBhMRUwEwYDVQQDDAxKb2huIEFsbGJlcmcxHjAcBgkqhkiG9w0BCQEW
D2pvaG5AYWxsYmVyZy5udTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyrAG
3iPY/DFjJFm0u/dvqzo8dwXyppF0aZzFZylWJqb6gK8YQr2VxCZjE0CnYWMguKmV
hGpxg1K83x9sUEfFuoCgvtwOwW1NvwJk0UjAFJ5XQWXSv15J6n+1UOU6MYI1ET+G
W3vS7ukmPgv4aoMwauSTMFve/rausGlzkgC44fsCAwEAAaOB0TCBzjAJBgNVHRME
AjAAMEYGA1UdIAQ/MD0wOwYKYIZIAYb4RQEHETAtMCsGCCsGAQUFBwIBFh9odHRw
czovL3d3dy50cnVzdC50ZWxpYS5jb20vcnBhMAsGA1UdDwQEAwIFoDARBglghkgB
hvhCAQEEBAMCB4AwWQYDVR0fBFIwUDBOoEygSoZIaHR0cDovL29uc2l0ZWNybC10
ZXN0LnRydXN0LnRlbGlhLmNvbS9UZWxpYVNvbmVyYVRlc3RTTUlNRS9MYXRlc3RD
UkwuY3JsMA0GCSqGSIb3DQEBBAUAA4GBAICqmYQCLaVb2PJvD+lcfnksxsPgdyhd
broCVLfFDzxmL5jU6vq0M/HseVkWAlT7ZuDI0M3yPa4g1k8FUrcdBO5nA4PvTbgh
2+3YusE4soK3giFCNR1bUzQWq3wS48UarEKpqC7LnK5b+dteu32M+WXq47jGF0F2
OAXgZZnjNbMa
-----END CERTIFICATE-----
Author
28 Feb 2005 7:11 AM
Peter Huang" [MSFT]
Hi

I am sorry if I make any confusion.
I use the hex editor e.g. UltraEditor to open the cer file and try to
observe the file and find that the serial number order is of the same of
.net one. While if I open the cer file in the explorer by doubleclick, the
order will be reverse. That is why I think the win32 approach have done
reverse.

Also I will help to try to forward your feedback.

Thanks for your understanding!

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
1 Mar 2005 3:39 AM
Peter Huang" [MSFT]
Hi

Now I am contacting security support team, and I will give you an update
ASAP.

Thanks for you understanding!

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
2 Mar 2005 1:29 AM
Peter Huang" [MSFT]
Hi

Based on my discussion with our support team, it seems that the behavior is
by design.
Here is the reply from senior escalation engineer.

X509Certificate.GetSerialNumber Method returns the serial number of the
X.509v3 certificate in "little endian" form.

====When using Crypto API===
CryptoAPI returns the serial number in the CERT_INFO structure.  The serial
number is returned in little endian format rather than big endian format. 

Here is what the documentation states:
SerialNumber
"BLOB containing the certificate's serial number. The least significant
byte is the zero byte of the pbData member of SerialNumber. The index for
the last byte of pbData. is one less than the value of the cbData member of
SerialNumber. The most significant byte is the last byte of pbData. Leading
0x00 or 0xFF bytes are removed. See CertCompareIntegerBlob."

It is normally up to the application using CryptoAPI to reverse the bytes
for display to match up with the standard CryptUI view (Explorer) or other
verisign tools.
====When using Crypto API===

X509Certificate.GetSerialNumber is returning the exact bytes returned by
CryptoAPI and is working as per the designed behavior.

It is up to the application to reverse the bytes to match up with other UI
tools.


If you still have any concern, please feel free to post here.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

Bookmark and Share