You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mifare Ultralight C 3DES认证过程中通信断开问题求助

Mifare Ultralight C 3DES认证过程中通信断开问题求助

我目前在实现Mifare Ultralight C卡的3DES认证流程,第一步发送1A 00认证命令一切正常,能收到AF开头带8字节挑战的响应,但当我发送AF+16字节加密后的响应 payload 时,NFC设备直接断开连接了,完全不知道问题出在哪。我使用的是Flutter的flutter_nfc_kit插件和pointycastle加密库,以下是我的完整代码和调试日志:

实现代码

import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
import 'package:pointycastle/pointycastle.dart';
import 'dart:typed_data';
import 'dart:math';

Future<bool> _authenticateUltralightC() async {
  final Uint8List key = Uint8List.fromList(List.filled(16, 0x00)); // 默认密钥
  Uint8List iv = Uint8List(8); // 初始IV(全0)

  try {
    // 步骤1: 发送认证命令
    Uint8List authCmd = Uint8List.fromList([0x1A, 0x00]);
    print('Auth Command: ${_bytesToHex(authCmd)}');
    Uint8List response = await FlutterNfcKit.transceive(authCmd);
    print('Auth Response: ${_bytesToHex(response)}');

    if (response.length != 9 || response[0] != 0xAF) {
      print('Error: Invalid response format');
      return false;
    }

    // 步骤2: 解密RndB
    final rndBEnc = response.sublist(1, 9);
    final rndB = _tripleDesDecrypt(rndBEnc, key, iv);
    print('RndB decrypted: ${_bytesToHex(rndB)}');

    // 更新IV用于下一步加密
    iv = rndBEnc;

    // 步骤3: 生成RndA并准备payload
    final rndA = _generateRandomBytes(8);
    final rndBRot = Uint8List.fromList([...rndB.sublist(1), rndB[0]]);
    final payload = Uint8List.fromList([...rndA, ...rndBRot]);

    print('RndA: ${_bytesToHex(rndA)}');
    print('RndB rotated: ${_bytesToHex(rndBRot)}');
    print('Payload: ${_bytesToHex(payload)}');

    // 加密payload
    final payloadEnc = _tripleDesEncrypt(payload, key, iv);
    print('Payload encrypted: ${_bytesToHex(payloadEnc)}');

    // 问题出在这一步:发送0xAF + 16字节加密数据(按官方协议)
    Uint8List step2Cmd = Uint8List.fromList([0xAF, ...payloadEnc]);
    print('Step2 Command (17 bytes): ${_bytesToHex(step2Cmd)}');

    // 执行到这里直接断开连接,后续代码完全不会执行
    response = await FlutterNfcKit.transceive(step2Cmd);
    print('Step2 Response: ${_bytesToHex(response)}');

    return true;
  } catch (e) {
    print('Auth error: $e');
    return false;
  }
}

// 3DES加密工具函数
Uint8List _tripleDesEncrypt(Uint8List data, Uint8List key, Uint8List iv) {
  // 将16字节密钥转换为24字节(K1, K2, K1)
  final key24 = Uint8List.fromList([...key, ...key.sublist(0, 8)]);
  final engine = DESedeEngine();
  final cipher = CBCBlockCipher(engine);
  cipher.init(true, ParametersWithIV(KeyParameter(key24), iv));

  final output = Uint8List(data.length);
  for (var offset = 0; offset < data.length; offset += 8) {
    cipher.processBlock(data, offset, output, offset);
  }
  return output;
}

// 3DES解密工具函数
Uint8List _tripleDesDecrypt(Uint8List data, Uint8List key, Uint8List iv) {
  final key24 = Uint8List.fromList([...key, ...key.sublist(0, 8)]);
  final engine = DESedeEngine();
  final cipher = CBCBlockCipher(engine);
  cipher.init(false, ParametersWithIV(KeyParameter(key24), iv));

  final output = Uint8List(data.length);
  for (var offset = 0; offset < data.length; offset += 8) {
    cipher.processBlock(data, offset, output, offset);
  }
  return output;
}

// 生成随机字节
Uint8List _generateRandomBytes(int length) {
  final random = SecureRandom('Fortuna');
  final seedBytes = Uint8List(32);
  final now = DateTime.now().millisecondsSinceEpoch;
  for (int i = 0; i < 32; i++) {
    seedBytes[i] = (now + i) % 256;
  }
  random.seed(KeyParameter(seedBytes));
  return random.nextBytes(length);
}

// 字节转十六进制字符串
String _bytesToHex(Uint8List bytes) {
  return bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(' ').toUpperCase();
}

调试日志

I (10685): Auth Command: 1A 00
/flutter I (10685): Auth Response: AF 1D B0 CA 48 03 29 5A 49
/flutter I (10685): RndB encrypted: 1D B0 CA 48 03 29 5A 49
/flutter I (10685): RndB decrypted: 7C 18 E3 C7 AE 81 60 18
/flutter I (10685): RndA generated: 3C 1E 9A D6 B3 C9 C7 0E
/flutter I (10685): RndB rotated: 18 E3 C7 AE 81 60 18 7C
/flutter I (10685): Payload (RndA + RndB'): 3C 1E 9A D6 B3 C9 C7 0E 18 E3 C7 AE 81 60 18 7C
/flutter I (10685): IV for encryption: 1D B0 CA 48 03 29 5A 49
/flutter I (10685): Payload encrypted: 7B 10 0B 0F A5 3B D2 1B D7 AD 4B 8E A8 32 F2 0E
/flutter I (10685): Step2 Command: AF 7B 10 0B 0F A5 3B D2 1B D7 AD 4B 8E A8 32 F2 0E
/flutter E(10685): Transceive: AF7B100B0FA53BD21BD7AD4B8EA832F20E error
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): java.lang.reflect.InvocationTargetException
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at java.lang.reflect.Method.invoke(Native Method)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin$Companion.transceive(FlutterNfcKitPlugin.kt:71)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin$Companion.access$transceive(FlutterNfcKitPlugin.kt:42)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin.handleMethodCall$lambda$4(FlutterNfcKitPlugin.kt:363)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin.$r8$lambda$HBcA1lvz_kCygGP5Zr_3a09ChIw(Unknown Source:0)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin$$ExternalSyntheticLambda4.run(Unknown Source:24)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at android.os.Handler.handleCallback(Handler.java:942)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at android.os.Handler.dispatchMessage(Handler.java:99)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at android.os.Looper.loopOnce(Looper.java:201)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at android.os.Looper.loop(Looper.java:288)
/im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin E(10685): 	at android.os.HandlerThread.run(HandlerThread.java:67)

我对照官方协议检查了好几遍流程:解密RndB、生成RndA、旋转RndB后拼接成16字节 payload、用3DES-CBC模式加密(密钥转成24字节的K1-K2-K1格式)、最后加上0xAF发送,逻辑上应该没问题,但就是在发送第二步命令时直接断开了。有没有大佬能帮我排查下?比如加密模式、IV的处理、命令格式有没有哪里不符合NFC卡的要求?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 07:23:03