Anonymous
[Sprintboot] [epassport] Аутентификация не удалась: не может вызвать "net.sf.scuba.smartcards.responseapdu.getsw ()", по
Сообщение
Anonymous » 29 янв 2025, 05:44
Я пишу этот код и много ошибок, я исправил много ошибок и эта последняя ошибка, и я не понимаю, что это значит и как исправить
package com.example.nfcpassportttbapi.nfccontroller; < /p>
Код: Выделить всё
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;
import javax.smartcardio.*;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.security.spec.AlgorithmParameterSpec;
import java.util.*;
@RestController
public class PassportController {
private static final Logger log = LoggerFactory.getLogger(PassportController.class);
private List extractOIDsFromCardAccess(byte[] cardAccessData) {
List 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();
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 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 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("
Подробнее здесь: [url]https://stackoverflow.com/questions/79395623/sprintbootepassportauthentication-failed-cannot-invoke-net-sf-scuba-smartc[/url]
1738118666
Anonymous
Я пишу этот код и много ошибок, я исправил много ошибок и эта последняя ошибка, и я не понимаю, что это значит и как исправить package com.example.nfcpassportttbapi.nfccontroller; < /p> [code]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; import javax.smartcardio.*; import java.awt.image.BufferedImage; import java.io.InputStream; import java.security.spec.AlgorithmParameterSpec; import java.util.*; @RestController public class PassportController { private static final Logger log = LoggerFactory.getLogger(PassportController.class); private List extractOIDsFromCardAccess(byte[] cardAccessData) { List 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(); 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 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 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(" Подробнее здесь: [url]https://stackoverflow.com/questions/79395623/sprintbootepassportauthentication-failed-cannot-invoke-net-sf-scuba-smartc[/url]