CryptoSys PKI Toolkit

SAT Mexico and the CryptoSys PKI Toolkit

SAT Mexico Support

The CryptoSys PKI Toolkit now includes full support for the private key files published by the Servicio de Administración Tributaria in Mexico. The private key file AAA010101AAA_0408021316S.key provided as a test is a PKCS-8 file encrypted using PBES2/rc2CBC. This key file can be read and decrypted using the CryptoSys PKI Toolkit. A copy is included in the VB project below.
New Release 6 August 2007
Released 6 August 2007:
New utility to create SAT Mexico digital signatures: see FirmaSAT.

The original key file and lots of other information including a sample XML file Muestra.xml (zipped, 1 kB) can be downloaded from ftp://ftp2.sat.gob.mx in folder /asistencia_ftp/publicaciones/solcedi

Contents

SAT Mexico Support | Signing and UTF-8 Data | Signing for SAT using C# | SAT X.509 Certificates and Base64 Format | SAT X.509 Certificate Serial Numbers

Signing and UTF-8 Data

The catch with signing digital documents according to the SAT requirements is that the text must be in UTF-8 format before creating the MD5 message digest. This only matters where the text contains accented characters like áéíóúñ. If your original string is in Latin-1 format (8-bit ASCII) and includes an accented character, it will not create the correct message digest. We have a solution.

VB6 project to sign XML file to SAT requirements: MexicoSAT.zip (13 kB)

Quick-and-dirty VB code to detect UTF-8 strings: basUTF8.bas.

A new in-built function to do the same thing: CNV_CheckUTF8

Jorge Perez has kindly prepared a port of MexicoSAT to PowerBuilder: see Example in Powerbuilder Script.

Signing for SAT using C#

Download the C# project MexicoSATcsharp which demonstrates techniques in signing and verifying data for SAT purposes, as well as how to verify an X.509 certificate. You will need to re-reference the diCrSysPKINet.dll class library in your project.

SAT X.509 Certificates and Base64 Format

The new functions X509_ReadStringFromFile and X509_SaveFileFromString introduced in version 3.0 of CryptoSys PKI now allow simple conversion of an X.509 certificate file to a base64 string and vice versa. The certificate is stored in a one-line base64 string, which can be cut-and-pasted into an XML file, for example
<?xml version="1.0" encoding="UTF-8"?>
<Comprobante fecha="2005-09-02T16:30:00" folio="1" noAprobacion="1" 
noCertificado="00001000000000000114" 
certificado="MIIDWjCCAkKgAwIBAgIUMDAwMDExMDAwMDAyMDA..."
serie="A" version="1.0">
The following example from the manual reads in the base64 string from the SAT Mexico test certificate and displays it. It then saves the string as a new certificate and uses the X509_CertThumb function to check that the two files are identical.
Dim nRet As Long
Dim strCertString As String
Dim strCertFile As String
Dim strNewFile As String
Dim strThumb1 As String
Dim strThumb2 As String

strCertFile = "aaa010101aaa_CSD.cer"

' Read in certificate file's data to a string
nRet = X509_ReadStringFromFile("", 0, strCertFile, 0)
Debug.Print "X509_ReadStringFromFile returns " & nRet
If nRet <= 0 Then Exit Sub  ' ERROR
strCertString = String(nRet, " ")
nRet = X509_ReadStringFromFile(strCertString, Len(strCertString), strCertFile, 0)
Debug.Print "For certificate '" & strCertFile & "':"
Debug.Print strCertString

' Save the string to a new certificate file, this time in PEM format
strNewFile = "aaa010101aaa_CSD.pem.cer"
nRet = X509_SaveFileFromString(strNewFile, strCertString, PKI_X509_FORMAT_PEM)
Debug.Print "X509_SaveFileFromString returns " & nRet
If nRet = 0 Then
    Debug.Print "Created new certificate file '" & strNewFile & "'"
End If

' Check that the two certificate files are identical by computing their SHA-1 thumbprints
strThumb1 = String(PKI_SHA1_CHARS, " ")
strThumb2 = String(PKI_SHA1_CHARS, " ")
nRet = X509_CertThumb(strCertFile, strThumb1, Len(strThumb1), 0)
nRet = X509_CertThumb(strNewFile, strThumb2, Len(strThumb2), 0)
Debug.Print "SHA-1(old)=" & strThumb1
Debug.Print "SHA-1(new)=" & strThumb2
If strThumb1 = strThumb2 Then
    Debug.Print "Certificates are identical"
Else
    Debug.Print "ERROR: certificates do not match"
End If
The output should look like this:
X509_ReadStringFromFile returns 1152
For certificate 'aaa010101aaa_CSD.cer':
MIIDWjCCAkKgAwIBAgIUMDAwMDEx...7D5F8SB7Li3zt9vbbMzBc5xGg==
X509_SaveFileFromString returns 0
Created new certificate file 'aaa010101aaa_CSD.pem.cer'
SHA-1(old)=5791650d63340129568c1eecc6566b2fdd8bbd4c
SHA-1(new)=5791650d63340129568c1eecc6566b2fdd8bbd4c
Certificates are identical

Old code, now superseded: How to read an X.509 certificate file and convert to base64 format and vice versa: x509_base64.bas.

SAT X.509 Certificate Serial Numbers

The X.509 standard is that the serial number is stored as an integer value. SAT in Mexico allocates serial numbers in the form of a hexadecimal-encoded value of a string of 20 ASCII digits, which represents an extremely large integer. Here is some VB6 code to extract the serial number in the required SAT format:
Dim nLen As Long
Dim strCertFile As String
Dim strSerialNumber As String
Dim strSerialSAT As String
' Extract the certificate's serial number
strCertFile = "AAA010101AAAsd.cer"
nLen = X509_CertSerialNumber(strCertFile, "", 0, 0)
If (nLen <= 0) Then Exit Sub
strSerialNumber = String(nLen, " ")
nLen = X509_CertSerialNumber(strCertFile, strSerialNumber, Len(strSerialNumber), 0)
Debug.Print "X.509 Serial Number=0x" & strSerialNumber
' Decode from hex-encoded integer to string of ASCII digits
strSerialSAT = StrConv(cnvBytesFromHexStr(strSerialNumber), vbUnicode)
Debug.Print "Decoded SAT Format ='" & strSerialSAT & "'"
For the sample X.509 certificate provided by SAT (AAA010101AAAsd.cer), this should produce the following output:
X.509 Serial Number=0x3030303031303030303030303030303030313134
Decoded SAT Format ='00001000000000000114'
Note that the code above is only applicable for certificates with serial numbers in this particular format. If you examine the test certificate using Microsoft's CERTMGR.EXE program (just double-click on the .CER file), you will see that the Serial Number value is given as
3030 3030 3130 3030 3030 3030 3030 3030 3031 3134
which is what our CryptoSys PKI program returns. This is the hexadecimal-encoded value of the decimal integer 275106190557734483187066766737145316642573594932!

This page last updated 6 November 2007

Valid HTML 4.01! Valid CSS

Home | PKI Home | Purchase | Cryptography Software Code | Contact us
Copyright © 2004-7 D.I. Management Services Pty Limited ABN 78 083 210 584, Sydney, Australia. All rights reserved.
<www.di-mgt.com.au>   <www.cryptosys.net>