admin管理员组

文章数量:1180476

i write this code and a lot of error , i fixed a lot error and this last error and i dont understand whats that mean and how to fix

package com.example.nfcpassportttbapi.NfcController;

import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.security.spec.AlgorithmParameterSpec;
import java.util.*;
import javax.smartcardio.*;
import org.jmrtd.AccessKeySpec;
import org.jmrtd.BACKey;
import org.jmrtd.BACKeySpec;
import org.jmrtd.PassportService;
import org.jmrtd.lds.icao.DG1File;
import org.jmrtd.lds.icao.DG2File;
import org.jmrtd.lds.icao.MRZInfo;
import org.jmrtd.lds.iso19794.FaceImageInfo;
import org.jmrtd.lds.iso19794.FaceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PassportController {
  private static final Logger log =
      LoggerFactory.getLogger(PassportController.class);
  private List<String> extractOIDsFromCardAccess(byte[] cardAccessData) {
    List<String> oids = new ArrayList<>();
    int index = 0;

    while (index < cardAccessData.length) {
      int tag = cardAccessData[index++] & 0xFF;

      // ตรวจสอบว่าเป็น OID (Tag 0x06)
      if (tag == 0x06) {
        int length = cardAccessData[index++] & 0xFF;
        byte[] oidBytes =
            Arrays.copyOfRange(cardAccessData, index, index + length);
        index += length;

        // แปลง OID เป็นสตริง
        StringBuilder oid = new StringBuilder();
        for (int i = 0; i < oidBytes.length; i++) {
          int value = oidBytes[i] & 0xFF;
          if (i == 0) {
            oid.append(value / 40).append(".").append(value % 40);
          } else {
            oid.append(".").append(value);
          }
        }
        oids.add(oid.toString());
      } else {
        // ข้าม tag อื่น ๆ
        int length = cardAccessData[index++] & 0xFF;
        index += length;
      }
    }

    return oids;
  }

  @GetMapping("/api/passport/read")
  public ResponseEntity<?> readPassport() {
    var result = new HashMap<String, Object>();

    try {
      // (1) ตั้งค่าข้อมูล BAC Key
      String passportNumber = "";
      String dateOfBirth = ""; // YYMMDD
      String dateOfExpiry = ""; // YYMMDD
      BACKeySpec bacKey = new BACKey(passportNumber, dateOfBirth, dateOfExpiry);

      log.info("BACKey => number={}, dob={}, doe={}", passportNumber,
          dateOfBirth, dateOfExpiry);

      // (2) ตรวจสอบเครื่องอ่านบัตร
      TerminalFactory factory = TerminalFactory.getDefault();
      List<CardTerminal> terminals = factory.terminals().list();

      if (terminals.isEmpty()) {
        log.warn("No PC/SC readers found.");
        result.put("error", "No PC/SC readers found");
        return ResponseEntity.badRequest().body(result);
      }

      CardTerminal terminal = terminals.get(0);
      log.info("Using terminal: {}", terminal.getName());

      // (3) รอจนกว่าจะมีบัตร
      if (!terminal.isCardPresent()) {
        log.info("Please place ePassport on the reader... (no timeout)");
        terminal.waitForCardPresent(0);
      }

      // (4) เชื่อมต่อกับบัตร
      Card card = terminal.connect("*");
      Test2 cs = new Test2(card); // ใช้ Test2 เป็น Custom CardService
      cs.open();
      log.info("Connected to card and opened CardService.");
      try {
        CardChannel cardChannel = card.getBasicChannel();

        // ส่งคำสั่ง SELECT FILE
        byte[] apduCommand = new byte[] {0x00, (byte) 0xA4, 0x04, 0x0C, 0x00};
        ResponseAPDU responseAPDU =
            cardChannel.transmit(new CommandAPDU(apduCommand));

        if (responseAPDU != null) {
          int sw = responseAPDU.getSW(); // อ่านค่า Status Word (SW)
          log.info("APDU Response SW: {}", Integer.toHexString(sw));

          // ตรวจสอบว่าบัตรตอบกลับด้วยค่า 0x9000 (Success) หรือไม่
          if (sw == 0x9000) {
            log.info("APDU command succeeded!");
          } else {
            log.warn("APDU command failed, SW: {}", Integer.toHexString(sw));
          }
        } else {
          log.error("ResponseAPDU is null, no response from the card");
        }
      } catch (Exception e) {
        log.error(
            "Exception while sending APDU command: {}", e.getMessage(), e);
        result.put("error", "APDU command failed: " + e.getMessage());
        cs.close();
        card.disconnect(false);
        return ResponseEntity.badRequest().body(result);
      }
      // (5) เปิด PassportService
      PassportService service =
          new PassportService(cs, PassportService.NORMAL_MAX_TRANCEIVE_LENGTH,
              PassportService.DEFAULT_MAX_BLOCKSIZE, true, false);
      service.open();
      log.info("PassportService opened.");

      try {
        boolean paceSuccess = false;

        // ดึงข้อมูล EF.CardAccess
        byte[] cardAccessData =
            service.getInputStream(PassportService.EF_CARD_ACCESS)
                .readAllBytes();
        List<String> oids = extractOIDsFromCardAccess(cardAccessData);
        log.info("PACE OIDs: {}", oids);

        for (String oid : oids) {
          try {
            service.doPACE(bacKey, oid, null);
            log.info("PACE succeeded with OID: {}", oid);
            paceSuccess = true;
            break;
          } catch (Exception e) {
            log.warn("PACE failed with OID {}: {}", oid, e.getMessage());
          }
        }

        if (!paceSuccess) {
          log.warn("PACE failed, trying BAC...");
          service.doBAC(bacKey);
          log.info("BAC succeeded.");
        }
      } catch (Exception e) {
        log.error("Authentication failed: {}", e.getMessage(), e);
        result.put("error", "Authentication failed: " + e.getMessage());
        cs.close();
        card.disconnect(false);
        return ResponseEntity.badRequest().body(result);
      }

      // (8) อ่าน DG1 -> MRZ
      try (InputStream dg1Input =
               service.getInputStream(PassportService.EF_DG1)) {
        DG1File dg1File = new DG1File(dg1Input);
        MRZInfo mrzInfo = dg1File.getMRZInfo();

        log.info("Document Number: {}", mrzInfo.getDocumentNumber());
        log.info(
            "Name: {}", mrzInfo.getSecondaryIdentifier().replace("<", " "));
        log.info(
            "Surname: {}", mrzInfo.getPrimaryIdentifier().replace("<", " "));

        result.put("documentNumber", mrzInfo.getDocumentNumber());
        result.put(
            "name", mrzInfo.getSecondaryIdentifier().replace("<", " ").trim());
        result.put(
            "surname", mrzInfo.getPrimaryIdentifier().replace("<", " ").trim());
        result.put("dateOfBirthMRZ", mrzInfo.getDateOfBirth());
        result.put("dateOfExpiryMRZ", mrzInfo.getDateOfExpiry());
        result.put("nationality", mrzInfo.getNationality());
      }

      // (9) อ่าน DG2 -> รูปใบหน้า
      try (InputStream dg2Input =
               service.getInputStream(PassportService.EF_DG2)) {
        DG2File dg2File = new DG2File(dg2Input);
        List<FaceInfo> faceInfos = dg2File.getFaceInfos();
        List<FaceImageInfo> faceImages = new ArrayList<>();
        for (FaceInfo faceInfo : faceInfos) {
          faceImages.addAll(faceInfo.getFaceImageInfos());
        }
        if (!faceImages.isEmpty()) {
          FaceImageInfo faceImageInfo = faceImages.get(0);
          BufferedImage image = ImageUtil.toBufferedImage(faceImageInfo);
          String faceBase64 = ImageUtil.toBase64(image);
          result.put("faceImageBase64", faceBase64);
          log.info("Face image read and converted to base64.");
        } else {
          log.warn("No face images in DG2");
          result.put("warningDG2", "No face images in DG2");
        }
      }

      // (10) ปิดการเชื่อมต่อ
      cs.close();
      card.disconnect(false);
      log.info("Disconnected card/CS. Done reading ePassport.");

      result.put("status", "success");
      return ResponseEntity.ok(result);

    } catch (Exception e) {
      log.error("Exception in readPassport: {}", e.getMessage(), e);
      var errorResult = new HashMap<String, Object>();
      errorResult.put("error", e.getMessage());
      return ResponseEntity.internalServerError().body(errorResult);
    }
  }
}

the requirement is i have a reader ACR1281 and i have epassport i must scan with nfc and show result of passport, the passport is good , and reader is not broke

本文标签: