无法使用 React Native NFC Manager 通过 Mifare Classic 密钥对扇区 0 进行身份验证

问题描述 投票:0回答:1

我正在开发一个React Native项目,使用react-native-nfc-manager库读取NFC Mifare Classic卡。我的目标是使用默认的 Mifare Classic 密钥 FFFFFFFFFFFF 验证并读取扇区 0 中的数据。然而,即使我知道密钥是正确的(它与 Mifare Classic Tool 和我以前的 Java 应用程序等其他应用程序一起使用),我的 React Native 实现始终无法进行身份验证。

我尝试过的 这是我对扇区 0 读取的实现:

NFCManagerService.ts

import NfcManager, { NfcTech } from 'react-native-nfc-manager';

class NFCManagerService {
    private static instance: NFCManagerService;

    private readonly CMD = {
        AUTH_A: 0x60, // Authenticate with Key A
        READ: 0x30,   // Read block
    };

    private constructor() { }

    public static getInstance(): NFCManagerService {
        if (!NFCManagerService.instance) {
            NFCManagerService.instance = new NFCManagerService();
        }
        return NFCManagerService.instance;
    }

    public async readSectorZero(logCallback: (message: string) => void): Promise<void> {
        try {
            logCallback('Initializing NFC...');
            await NfcManager.requestTechnology(NfcTech.MifareClassic);
            logCallback('NFC initialized.');

            const tag = await NfcManager.getTag();
            if (!tag) {
                throw new Error('No tag detected.');
            }
            logCallback(`Tag detected: ${tag.id}`);

            const key = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
            const keyHex = key.map(b => b.toString(16).padStart(2, '0')).join('');
            logCallback(`Attempting Auth A Sector 0 with key: ${keyHex}`);

            if (await this.authenticateSector(0, key)) {
                logCallback(`✓ Auth A Sector 0 succeeded with key: ${keyHex}`);

                const data = await this.readBlock(0);
                if (data) {
                    logCallback(`Data from Block 0: ${Array.from(data).map(b => b.toString(16).padStart(2, '0')).join(' ')}`);
                } else {
                    logCallback('Failed to read data from Block 0.');
                }
            } else {
                logCallback(`✗ Auth A Sector 0 failed with key: ${keyHex}`);
            }
        } catch (error) {
            logCallback(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
        } finally {
            await NfcManager.cancelTechnologyRequest();
            logCallback('NFC released.');
        }
    }

    private async authenticateSector(sector: number, key: number[]): Promise<boolean> {
        try {
            const authCommand = [this.CMD.AUTH_A, sector * 4, ...key];
            await NfcManager.transceive(authCommand);
            return true;
        } catch {
            return false;
        }
    }

    private async readBlock(blockIndex: number): Promise<Uint8Array | null> {
        try {
            const readCommand = [this.CMD.READ, blockIndex];
            const response = await NfcManager.transceive(readCommand);
            return new Uint8Array(response);
        } catch {
            return null;
        }
    }
}

export default NFCManagerService;

ReaderScreen.tsx

import React, { useState } from 'react';
import { View, Button, Text, ScrollView, StyleSheet } from 'react-native';
import NFCManagerService from '../services/NFCManagerService';

const ReaderScreen = () => {
    const [logs, setLogs] = useState<string[]>([]);
    const [isReading, setIsReading] = useState(false);

    const addLog = (message: string) => {
        setLogs(prevLogs => [...prevLogs, message]);
    };

    const handleReadSectorZero = async () => {
        setIsReading(true);
        setLogs([]);
        try {
            const nfcService = NFCManagerService.getInstance();
            await nfcService.readSectorZero(addLog);
        } catch {
            addLog('Error reading the badge.');
        } finally {
            setIsReading(false);
        }
    };

    return (
        <View style={styles.container}>
            <Button
                title={isReading ? 'Reading...' : 'Read Sector 0'}
                onPress={handleReadSectorZero}
                disabled={isReading}
            />
            <ScrollView style={styles.logContainer}>
                {logs.map((log, index) => (
                    <Text key={index} style={styles.logText}>{log}</Text>
                ))}
            </ScrollView>
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        padding: 20,
    },
    logContainer: {
        marginTop: 20,
        maxHeight: 400,
        width: '100%',
        backgroundColor: '#f4f4f4',
        padding: 10,
        borderRadius: 8,
    },
    logText: {
        fontSize: 14,
        marginBottom: 5,
    },
});

export default ReaderScreen;

问题:

我可以使用 NfcManager.transceive 检测卡并发送命令。 该卡是一张空白 Mifare Classic 1K,扇区 0 应该可以使用默认密钥 FFFFFFFFFFFF 读取。 同一张卡和钥匙与 Mifare Classic Tool 应用程序完美配合。 这是我的应用程序尝试身份验证时的日志:

react-native mifare react-native-nfc-manager
1个回答
0
投票

有人可以知道答案或者我做错了什么吗?

© www.soinside.com 2019 - 2024. All rights reserved.