Пример #1
0
        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.manager != null)
                {
                    this.manager.CardConnect(this.readerName, false);

                    APDU_Response _Response = new APDU_Response();

                    //1. Select Applet EF_CardAccess: Comando= Class=00 Ins=A4 P1=04 P2=00 P3=0C Data= A00000001840000001634200
                    byte[] Data = new byte[] { 0x01, 0x1E };

                    //00 A4 00 00 00 <- MAIN FILE
                    byte[] _APDU = this.manager.createAPDU_Command(0x00, 0xA4, 0x04, 0x00, (byte)Data.Length, Data);
                    //_APDU = this.manager.createAPDU_Command(0x00, 0xA4, 0x04, 0x00, 0x00, 0x00);
                    //_Response = this.manager.CardTransmit(_APDU);

                    //if (_Response.is_ok)
                    //{
                    //	/* 6F 64 84 07 A0 00 00 00 18 43 4D A5 59 73 4A 06 07 2A 86 48 86 FC 6B 01 60 0C 06 0A 2A 86 48 86 FC
                    //	 * 6B 02 02 01 01 63 09 06 07 2A 86 48 86 FC 6B 03 64 0B 06 09 2A 86 48 86 FC 6B 04 02 55 65 0B 06 09
                    //	 * 2B 85 10 86 48 64 02 01 03 66 0C 06 0A 2B 06 01 04 01 2A 02 6E 01 02 9F 6E 06 12 91 21 72 03 00 9F
                    //	 * 65 01 FF [90 00]
                    //	 */
                    //}

                    /*
                     * 1. Select - select the epassport application
                     * 2. Get Challenge
                     * 3. External Authenticate
                     * 4. Read Binary(protected by secure messaging) - read the DG1 file which contains basic passport holder info
                     * 5. Read Binary(protected by secure messaging) - read the DG2 file which contains the photo of the passport holder info
                     */


                    //1. Select App ePassport MRZ: "04", "0C", "A0 00 00 02 47 10 01"
                    Data      = new byte[] { 0xA0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01 };
                    _APDU     = this.manager.createAPDU_Command(0x00, 0xA4, 0x04, 0x0C, (byte)Data.Length, Data);
                    _Response = this.manager.CardTransmit(_APDU);
                    //[90 00]

                    if (_Response.is_ok)
                    {
                        //2. Get Challenge :
                        _APDU     = this.manager.createAPDU_Command(0x00, 0x84, 0x00, 0x00, 0x08);
                        _Response = this.manager.CardTransmit(_APDU);
                        // D7 FB D7 CE 84 C3 CD 09 [90 00]

                        if (_Response.is_ok)
                        {
                            //3. EXTERNAL AUTENTICATE:
                            Data      = _Response.Data;
                            _APDU     = this.manager.createAPDU_Command(0x00, 0x82, 0x00, 0x00, (byte)Data.Length, Data);
                            _Response = this.manager.CardTransmit(_APDU);

                            if (_Response.is_ok)
                            {
                            }
                        }
                        else
                        {
                            MessageBox.Show(_Response.ToString(), "Error Inesperado", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.StackTrace, "Error Inesperado", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void Leer_Cedula_EnAccion()
        {
            try
            {
                if (this.manager != null)
                {
                    this.manager.CardConnect(this.readerName, false);
                    APDU_Response _Response = new APDU_Response();

                    /* AQUI VAMOS A LEER LOS DATOS DE LA CEDULA URUGUAYA USANDO PARA ELLO UN LECTOR CON CONTACTO
                     * TAMBIEN SE PUEDE CON UN LECTOR 'CONTACTLESS' PERO ES MAS COMPLICADO  */

                    //1. SELECT_FILE: Applet IAS Comando= Class=00 Ins=A4 P1=04 P2=00 P3=0C Data= A00000001840000001634200
                    byte[] Data  = new byte[] { 0xA0, 0x00, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x01, 0x63, 0x42, 0x00 };
                    byte[] _APDU = this.manager.createAPDU_Command(0x00, 0xA4, 0x04, 0x00, (byte)Data.Length, Data);
                    _Response = this.manager.CardTransmit(_APDU);
                    //_Response:  Ret=00, SW=9000(FF00), Data=00

                    //2. SELECT_FILE: Datos_BIO         00 A4 00 00 02 [70 02] 00   <- [70 02] es el ID del archivo
                    _APDU     = this.manager.createAPDU_Command(0x00, 0xA4, 0x00, 0x00, 0x02, 0x70, 0x02, 0x00);
                    _Response = this.manager.CardTransmit(_APDU);
                    // _Response: Ret=00, SW1=61, SW2=xx --> xx es la posicion del FCI Template

                    //3. GET_RESPONSE: 00 CO 00 00 xx  <-- (xx es el SW2 del comando anterior)
                    _APDU     = this.manager.createAPDU_Command(0x00, 0xC0, 0x00, 0x00, _Response.sw2);
                    _Response = this.manager.CardTransmit(_APDU);

                    /* _Response.SW: 90000(FF00),  Ret=00,
                     * _Response.Data: FCI Template ->  6F 13  81 02 [00 7B] 82 01  01 83  02 70  02 8A  01 05  8C 03 03
                     *   6F <- Tag indicando que esto es un FCI Template
                     *   13 <- Largo total del Template: 13 (hex->Int) = 19 bytes
                     *   81 <- Tag para indicar el Tamaño del Archivo
                     *   02 <- Largo del tag que indica el Tamaño del Archivo (2 bytes)
                     *   [00 7B]  <- Tamaño del Archivo: [007B] = 123 bytes
                     *   [Otros bytes sin relevancia para este caso]  */

                    //4. READ_BINARY: Datos_BIO		00 B0 00 00 [xx yy]  <- [xx yy] es el Tamaño del archivo del comando anterior
                    _APDU     = this.manager.createAPDU_Command(0x00, 0xB0, 0x00, _Response.Data[4], _Response.Data[5]);
                    _Response = this.manager.CardTransmit(_APDU);

                    /* _Response.SW: 90000(FF00),  Ret=00,
                     * _Response.Data = TLV Template:
                     * 1F 01 0E 43 48 41 43 C3 93 4E 20 52 41 4E 47 45 4C 1F 02 00 1F 03 08 4A 48 4F 4C 4C
                     * 4D 41 4E 1F 04 03 43 4F 4C 1F 05 08 31 38 30 34 31 39 37 35 1F 06 0D 53 41 4E 54 41
                     * 4E 44 45 52 2F 43 4F 4C 1F 07 08 35 34 39 36 39 38 34 36 1F 08 04 14 08 20 16 1F 09
                     * 08 33 30 30 36 32 30 31 39 1F 0A 1B 52 45 53 49 44 45 4E 54 45 20 4C 45 47 41 4C 20
                     * 44 4E 4D 20 31 31 31 34 2F 30 35 */

                    //La clase 'TLV_Cedula' se encarga de decodificar los datos biograficos de la Persona:
                    this.Datos_Cedula = new TLV_Cedula(_Response.Data);
                    if (this.Datos_Cedula != null)
                    {
                        this.BeginInvoke(this.Delegado2, "DatosPersona");
                    }


                    /**** AHORA VAMOS A LEER LA FOTO, ESTE PROCESO ES ALGO LENTO *****/

                    //5. SELECT_FILE: Foto  00 A4 00 00 02 [70 04] 00  <- [70 04] es el ID del archivo
                    _APDU     = this.manager.createAPDU_Command(0x00, 0xA4, 0x00, 0x00, 0x02, 0x70, 0x04, 0x00);
                    _Response = this.manager.CardTransmit(_APDU);
                    // _Response: Ret=00, SW1=61, SW2=xx --> xx es la posicion del FCI Template

                    //6. GET_RESPONSE: 00 CO 00 00 xx <-- (xx es el SW2 del comando anterior)
                    _APDU     = this.manager.createAPDU_Command(0x00, 0xC0, 0x00, 0x00, _Response.sw2);
                    _Response = this.manager.CardTransmit(_APDU);

                    /* _Response.SW: 90000(FF00),  Ret=00,
                     * _Response.Data: FCI Template =
                     *    6F 13 81 02 [25 B9] 82 01 01 83 02 70 04 8A 01 05 8C 03 03 [FF 00]
                     *    0  1  2  3   4  5   6  7  .. ..
                     *  [25 B9] = 9657 bytes => Tamaño del FCI Template que contiene la imagen
                     *  [Otros bytes sin relevancia para este caso]              */

                    //7. Obtengo el Tamaño esperado de todo el Archivo que contiene la Imagen (incluye 5 bytes del Tag):
                    int foto_len = int.Parse(this.manager.byteToHexa(
                                                 new byte[] { _Response.Data[4], _Response.Data[5] }, 2, false), System.Globalization.NumberStyles.HexNumber);
                    int    nro_corridas = (foto_len / 255) + 1;                     //<- Numero de corridas necesarias para recuperar toda la Foto
                    byte[] foto_bytes   = new byte[foto_len];                       //<- Buffer para almacenar la Foto

                    //1. Recupero los primeros 255 bytes, incluye 5 bytes del FCI Template
                    //READ_BINARY FotoPersona:  00 B0 00 00 FF  <- P1 y P2 son el Offset donde se va leyendo el archivo, en este caso [00 00]
                    _APDU     = this.manager.createAPDU_Command(0x00, 0xB0, 0x00, 0x00, 0xFF);
                    _Response = this.manager.CardTransmit(_APDU);

                    /*  _Response.SW: 90000(FF00), Ret=00,
                     *  _Response.Data:  FCI Template + Foto
                     *  3F 01 <- Tag
                     *  82    <- Tamaño en 2 bytes
                     *      25 B4 <- Tamaño de la Imagen = 9.652 bytes
                     *      [3F 01 82 25 B4] FF D8 FF E0 00 10 4A 46 49 46 00 01 01 00 00 01 00 01 00 00 FF DB 00 43 00 08 06 06 07 06 05 08 07 07 07
                     *      09 09 08 0A 0C 14 0D 0C 0B 0B 0C 19 12 13 0F 14 1D 1A 1F 1E 1D 1A 1C 1C 20 24 2E 27 20 22 2C 23 1C 1C 28 37 29 2C 30 31
                     *      34 34 34 1F 27 39 3D 38 32 3C 2E 33 34 32 FF DB 00 43 01 09 09 09 0C 0B 0C 18 0D 0D 18 32 21 1C 21 32 32 32 32 32 32 32
                     *      32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
                     *      32 32 32 FF C0 00 11 08 01 40 00 F0 03 01 22 00 02 11 01 03 11 01 FF C4 00 1F 00 00 01 05 01 01 01 01 01 01 00 00 00 00
                     *      00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B FF C4 00 B5 10 00 02 01 03 03 02 04 03 05 05 04 04 00 00 01 7D 01 02 03 00
                     *      04 11 05 12 21 31 41 06 13 51 61 07 22 71 14 00 */

                    //Voy guardando los bytes recuperados en el Buffer de la Foto:
                    if (_Response.is_ok && _Response.has_data)
                    {
                        Array.Copy(_Response.Data, 0, foto_bytes, 0, _Response.Data.Length);
                    }

                    byte _P2    = 0xFF;                  //<- Incremento el Offset en 255 ('FF'),
                    int  ult_ix = _Response.Data.Length; //<- Posicion del Ultimo(+1) Byte Recuperado

                    //Ahora a extraer el resto del archivo:
                    //Se hace asi porque solo podemos extraer 255 bytes cada vez

                    /*	CLA INS P1 P2 Le
                     *      ----------------
                     *      00   B0 00 FF FF	<- Siguientes 255 bytes (no hay tag)
                     *      00   B0 01 FE FF
                     *      00   B0 02 FD FF
                     *      00   B0 03 FC FF
                     *      00   B0 04 FB FF
                     *      ..   .. .. .. ..  <- Hasta Terminar
                     */
                    for (int _P1 = 0; _P1 <= nro_corridas; _P1++)
                    {
                        //READ_BINARY FotoPersona:
                        _APDU     = this.manager.createAPDU_Command(0x00, 0xB0, (byte)_P1, _P2, 0xFF);
                        _Response = this.manager.CardTransmit(_APDU);

                        /* _Response.SW: 90000(FF00), Ret=00,
                         * _Response.Data: [Bytes de la foto]    */

                        if (_Response.is_ok && _Response.has_data)
                        {
                            //Voy guardando los bytes recuperados en el Buffer de la Foto:
                            Array.Copy(_Response.Data, 0, foto_bytes, ult_ix, _Response.Data.Length);

                            _P2--;                              //<- vamos reduciendo el Offset para la siguiente corrida
                            ult_ix += _Response.Data.Length;    //<- Posicion del Ultimo(+1) Byte Recuperado
                        }
                    }

                    // Quitar los 5 bytes del Tag FCI Template y Guardar la Imagen en un Archivo JPG:
                    byte[] foto_ = new byte[foto_bytes.Length - 5];
                    Array.Copy(foto_bytes, 5, foto_, 0, foto_bytes.Length - 5);

                    //Adjunto la foto a los demas datos de la Persona:
                    this.Datos_Cedula.foto_persona = foto_;
                    this.BeginInvoke(this.Delegado2, "Foto");

                    using (System.Drawing.Image image = System.Drawing.Image.FromStream(new System.IO.MemoryStream(foto_)))
                    {
                        image.Save(@"C:\Temp\foto2.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                        if (System.IO.File.Exists(@"C:\Temp\foto2.jpg"))
                        {
                            //abre con el programa predeterminado:
                            System.Diagnostics.Process.Start(@"C:\Temp\foto2.jpg");
                        }
                    }
                }
            }
            catch (ThreadAbortException)
            {
                MiProceso1.Join();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.StackTrace, "Error Inesperado", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                this.BeginInvoke(this.Delegado2, "Terminar");
            }
        }