none
leer info de smart card (DNI electronico Uruguay) RRS feed

  • Pregunta

  • Quiero leer la informacion publica de un DNI electronico, Documento Nacional de Identificacion con chip electronico, una smart card iso 7816.

    de Uruguay

    estas son las especificaciones de AGESIC : https://centroderecursos.agesic.gub.uy/web/seguridad/wiki/-/wiki/Main/Gu%C3%ADa+de+uso+de+CI+electr%C3%B3nica+a+trav%C3%A9s+de+APDU

    Aqui explica todo el tema de los comandos APDU

    Este es un ejemplo en lenguaje C

    https://ludovicrousseau.blogspot.com/2010/04/pcsc-sample-in-c.html

    Este es un ejemplo en lenguaje Python

    https://medium.com/overactive/firma-digital-uruguay-c74ab12e586

    Este es un github en java, yo opino que no funciona, pero no lo ejecute

    https://github.com/agesic-eid/Interfaz-datosci-apdu

    este es otro ejemplo de github en java

    https://github.com/eIDuy/apdu-services

    este es otro codigo en python

    #!/usr/bin/python
    
    #############################################################################################
    #   Algunos de los metodos del codigo publicado por Gustavo Azambuja en :                   # 
    #   https://gist.github.com/gazambuja/a55b75422a5a18c50e6d1ba7f5f44eea                      #
    #   fueron refactorizados y comentados para su uso en el proyecto de seguridad de la        #
    #   Universidad Catolica del Uruguay en el primer semestre de 2018 por el grupo 9 :         #
    #   Facundo Hernandez, Francisco Perdomo, Ricardo Umpierrez                                 #
    #############################################################################################
    
    import hashlib, sys, time
    from smartcard.CardType import ATRCardType, AnyCardType
    from smartcard.CardRequest import CardRequest
    from smartcard.CardConnection import CardConnection
    from smartcard.util import toHexString, toBytes
    
    action = userpin = stringhash = False
    
    ########### COMANDOS PRECARGADOS ####################
    #               | CLA | INS | P1 | P2  |  LC |      DATA  ...                                  
    selectIAS =     [0x00, 0xA4, 0x04, 0x00, 0x0C, 0xA0, 0x00, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x01, 0x63, 0x42, 0x00, 0x00]
    verifyPIN =     [0x00, 0x20, 0x00, 0x11, 0x0C]
    
    MSE_SET_DST =   [0x00, 0x22, 0x41, 0xB6, 0x06]
    PSO_HASH =      [0x00, 0x2A, 0x90, 0xA0, 0x20]
    PSO_CDS =       [0x00, 0x2A, 0x9E, 0x9A, 0x00, 0xFF, 0x00]
    ####################################################
    
    if( len(sys.argv) == 1 ):
        print "Faltan argumentos"
    else:
        action = sys.argv[1]
        userpin = sys.argv[2] if len(sys.argv) > 3 else False
        stringhash = sys.argv[3] if len(sys.argv) > 3 else False
    
    cardtype = ATRCardType( toBytes( "3B 7F 94 00 00 80 31 80 65 B0 85 03 00 EF 12 0F FF 82 90 00" ) ) # Solo eCI de UY
    cardrequest = CardRequest( timeout=20, cardType=cardtype )
    
    if (len(cardrequest.getReaders()) == 0 ):
        print "Lector no conectado"
    
    def encrypt_string(hash_string):
        sha_signature = hashlib.sha256(hash_string.encode()).hexdigest()
        return sha_signature
    
    def enviarAPDU(cmd):
        data, sw1, sw2 = cardservice.connection.transmit(cmd)
        return [data, sw1, sw2];
    
    def toHex(str):
        m = len(str)
        lst = []
        for i in xrange(0, m, 2):
            lst.append( int('0x' + str[i] + str[i + 1], 16) )
        return lst
    
    def toPinHex(pin):
        m = len(pin)
        lst = []
        for i in xrange(0, 12, 1):
            if(i >= m):
                lst.append( int('0x00', 16))
            else:
                lst.append( int('0x3' + pin[i], 16))
        return lst
    
    def init():
    
        global cardservice
        cardservice = cardrequest.waitforcard()
        cardservice.connection.connect( CardConnection.T0_protocol )
    
        ########### COMANDO selectIAS ################
        data, sw1, sw2 = enviarAPDU( selectIAS )          
        if ( sw1 != 0x90 and sw2 != 0x0 ) :
            print "ERROR AL LEER DOCUMENTO"
        else:
            time.sleep(1)
        
        ########### COMANDO verifyPIN ################
        data, sw1, sw2 = enviarAPDU( verifyPIN + toPinHex(userpin) )
        if ( sw1 == 0x90 and sw2 == 0x0 ) :
            
            ########### COMANDO MSE_SET_DST ################
            data, sw1, sw2 = enviarAPDU( MSE_SET_DST + [0x84, 0x01, 0x01, 0x80, 0x01, 0x02] )
    
            ########### COMANDO PSO_HASH ################
            data, sw1, sw2 = enviarAPDU( PSO_HASH + [0x90, 0x19] + MIHASH )
    
            ########### COMANDO PSO_Compute Digital Signature: ################
            data, sw1, sw2 = enviarAPDU( PSO_CDS )
    
            print encrypt_string(toHexString(data).replace(" ", ""))
    
        else :
            print "PIN INVALIDO"
    
    ###########################################################################
    ### Hay dos acciones definidas:                                         ###
    ###     - readerData ( void ) : imprime la marca y modelo del Lector    ###
    ###     - firmar (pin, string): hace un hash y encripta con la clave    ###
    ###                             privada un string pasado por parametro  ###
    ###########################################################################
    
    if ( action == 'readerData' ):
        print "reader" + str(cardrequest.getReaders()[0])
    
    elif ( action == 'firmar' ):
        MIHASH = toHex(encrypt_string(stringhash))
        init()
    else:
        print "ACCION NO DEFINIDA"

    mi desconocimiento de python y mi escaso conocimiento de java me impiden encontrar equivalentes en C#, pese a ello e escrito el siguiente codigo que funciona, pero no me brinda todos los datos publicos de la smart card

    con la dll System.Security
    
    con este using:
    using System.Security.Cryptography.X509Certificates;
    
    X509Store store = new X509Store(StoreName.My);
                store.Open(OpenFlags.ReadOnly);
                string certSubject;
                string certGetName;
                string certFriendlyName;
                string certGetEffectiveDateString;
                string certGetExpirationDateString;
                string certGetIssuerName;
                string certGetKeyAlgorithm;
                string certGetKeyAlgorithmParametersString;
                string certGetPublicKeyString;
                string certGetRawCertDataString;
                string certGetSerialNumberString;
                string certIssuer;
                string certSerialNumber;
                string certThumbprint;
                StringBuilder sb = new StringBuilder();
                if (store.Certificates.Count > 0)
                {
                    foreach (X509Certificate2 cert in store.Certificates)
                    {
                        if (cert.Issuer.Contains("Ministerio del Interior"))
                        {
                            certFriendlyName = cert.FriendlyName;
                            certGetEffectiveDateString = cert.GetEffectiveDateString();
                            certGetExpirationDateString = cert.GetExpirationDateString();
                            certGetIssuerName = cert.GetIssuerName();
                            certGetKeyAlgorithm = cert.GetKeyAlgorithm();
                            certGetKeyAlgorithmParametersString = cert.GetKeyAlgorithmParametersString();
                            certGetName = cert.GetName();
                            certGetPublicKeyString = cert.GetPublicKeyString();
                            certGetRawCertDataString = cert.GetRawCertDataString();
                            certGetSerialNumberString = cert.GetSerialNumberString();
                            certIssuer = cert.Issuer;
                            certSerialNumber = cert.SerialNumber;
                            certSubject = cert.Subject;
                            certThumbprint = cert.Thumbprint;
                            sb.Append("certFriendlyName : " + certFriendlyName + Environment.NewLine);
                            sb.Append("certGetEffectiveDateString : " + certGetEffectiveDateString + Environment.NewLine);
                            sb.Append("certGetExpirationDateString : " + certGetExpirationDateString + Environment.NewLine);
                            sb.Append("certGetIssuerName : " + certGetIssuerName + Environment.NewLine);
                            sb.Append("certGetKeyAlgorithm : " + certGetKeyAlgorithm + Environment.NewLine);
                            sb.Append("certGetKeyAlgorithmParametersString : " + certGetKeyAlgorithmParametersString + Environment.NewLine);
                            sb.Append("certGetName : " + certGetName + Environment.NewLine);
                            sb.Append("certGetPublicKeyString : " + certGetPublicKeyString + Environment.NewLine);
                            sb.Append("certGetRawCertDataString : " + certGetRawCertDataString + Environment.NewLine);
                            sb.Append("certGetSerialNumberString : " + certGetSerialNumberString + Environment.NewLine);
                            sb.Append("certIssuer : " + certIssuer + Environment.NewLine);
                            sb.Append("certSerialNumber : " + certSerialNumber + Environment.NewLine);
                            sb.Append("certSubject : " + certSubject + Environment.NewLine);
                            sb.Append("certThumbprint : " + certThumbprint + Environment.NewLine);
                            
                        }
                    }
                }

    por otro lado he escrito este otro codigo, pero no consigo encontrar los comandos APDU correctos para obtener los datos

    using PCSC;
    
     private void bLeoCIe_Click(object sender, EventArgs e)
            {
                SCardContext hContext = new SCardContext();
                hContext.Establish(SCardScope.System);
                string[] szReaders = hContext.GetReaders();
                if (szReaders.Length <= 0)
                {
                    // no hay smartcard
                }
                else
                {                
                    SCardReader reader = new SCardReader(hContext);
                    SCardError err = reader.Connect(szReaders[0], SCardShareMode.Shared, SCardProtocol.T0 | SCardProtocol.T1);
                    
                    CheckErr(err);
                    IntPtr pioSendPci = SCardPCI.T0;
                    switch (reader.ActiveProtocol)
                    {
                        case SCardProtocol.T0:
                            pioSendPci = SCardPCI.T0;
                            break;
                        case SCardProtocol.T1:
                            pioSendPci = SCardPCI.T1;
                            break;                    
                    }
                    byte[] pbRecvBuffer = new byte[256];
                    byte[] cmd1 = new byte[] { 0x00, 0xA4, 0x04, 0x00, 0x0A, 0xA0,
                        0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0C, 0x06, 0x01 };
                    err = reader.Transmit(pioSendPci, cmd1, ref pbRecvBuffer);
                    
                    CheckErr(err);
                    StringBuilder sr = new StringBuilder();
                    sr.Append("response : ");
                    for (int i = 0; i < pbRecvBuffer.Length; i++)
                    {
                        sr.Append(pbRecvBuffer[i]); //0:x2
                    }
    
    
                    pbRecvBuffer = new byte[256];
                    byte[] cmd2 = new byte[] { 0x00, 0x00, 0x00, 0x00 };
                    err = reader.Transmit(pioSendPci, cmd2, ref pbRecvBuffer);
                    CheckErr(err);
    
                    sr = new StringBuilder();
                    sr.Append("response : ");
                    for (int i = 0; i < pbRecvBuffer.Length; i++)
                    {
                        sr.Append(pbRecvBuffer[i]); //0:x2
                    }
    
    
    
                    pbRecvBuffer = new byte[256];
                    byte[] cmd3 = new byte[] { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x70, 0x00 };
                    err = reader.Transmit(pioSendPci, cmd3, ref pbRecvBuffer);
                    CheckErr(err);
    
                    pbRecvBuffer = new byte[256];
                    byte[] cmd4 = new byte[] { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x70, 0x01 };
                    err = reader.Transmit(pioSendPci, cmd4, ref pbRecvBuffer);
                    CheckErr(err);
    
                    pbRecvBuffer = new byte[256];
                    byte[] cmd5 = new byte[] { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x70, 0x02 };
                    err = reader.Transmit(pioSendPci, cmd5, ref pbRecvBuffer);
                    CheckErr(err);
    
                    pbRecvBuffer = new byte[256];
                    byte[] cmd6 = new byte[] { 0x00, 0xA4, 0x04, 0x00, 0x0C, 0xA0, 0x00, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x01, 0x63, 0x42, 0x00, 0x00 };
                    err = reader.Transmit(pioSendPci, cmd6, ref pbRecvBuffer);
                    CheckErr(err);
    
                    pbRecvBuffer = new byte[256];
                    byte[] cmd7 = new byte[] { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x70, 0x04 };
                    err = reader.Transmit(pioSendPci, cmd7, ref pbRecvBuffer);
                    CheckErr(err);
    
                    pbRecvBuffer = new byte[256];
                    byte[] cmd8 = new byte[] { 0x00, 0xA4, 0x04, 0x00, 0x0A, 0xA0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0C, 0x06, 0x01 };
                    err = reader.Transmit(pioSendPci, cmd8, ref pbRecvBuffer);
                    CheckErr(err);
    
                    pbRecvBuffer = new byte[256];
                    byte[] cmd9 = new byte[] { 0x00, 0x00, 0x00, 0x00 };
                    err = reader.Transmit(pioSendPci, cmd9, ref pbRecvBuffer);
                    CheckErr(err);
    
    
                    hContext.Release();
                }
    }
    
     static void CheckErr(SCardError err)
            {
                if (err != SCardError.Success)
                {
                    // error
                }
            }

    la libreria que utilice es: PCSC y PCSC.iso7816

    el cmd2 me manda un array de 256 caracteres todos en 0 y todos los otros cmd1 ... cmd9 solo un array de  2 caracteres


    Hugo González (Macgyber)


    • Editado macgyber martes, 11 de junio de 2019 21:33
    sábado, 8 de junio de 2019 15:19

Todas las respuestas