Android程序运行分析——中等复杂程度的NTAG I2C Demo为例(六)

本文针对NT3H2111芯片DataSheet中有关Authenticate的内容进行整理汇总,用一种比较好理解的方式叙述

DataSheet下载链接:https://www.nxp.com/docs/en/data-sheet/NT3H2111_2211.pdf


NFC技术的一个重要应用场景是,移动支付领域,因此相关的安全技术是必不可少的

对于这种安全认证技术,NXP公司的这款NT3H2111芯片,自然有很多优化的措施,本文介绍NXP这款产品是如何在芯片的层面完成密码认证的机制的

下图是NFC角度的NT3H2111芯片的memory组织方式

可以看到,从NFC的角度,芯片的第一层框架为sector,主要的东西都放在第一个sector里面;第二层框架是page,每一个sector有255个page,;第三层框架是Byte,也就是字节,一个Page有4个字节

下面描述一下整个认证的过程:

首先,一开始的时候密码保护状态肯定是禁用的,这个时候请关注一下AUTH0这个位置,其实本质上AUTH0就是一个位于Sector0并且Page地址在E3h的第4个Byte(从0开始数是第4个)的那个Byte

AUTH0的作用是,指定在SECTOR0中,被保护的区域是从哪里开始的,也就是被保护区域的起始地址。当然若AUTH0里的值大于EBh,则密码保护会被禁用

关于AUTH0,有一句话我还没看明白,先挖个坑

从NFC的视角来看,有一块区域是专门用于实现这个密码认证的,如图所示,从E3H到E7H

如果从I2C的角度来看,是block从38H到39H

当然这款区域是在EEPROM里的(SRAM相当于内存,掉电就没了,显然这些重要的东西不应该放在SRAM里面)

我们已经知道,这款NFC芯片的memory(不知道应该怎么翻译)根据存储体性质的不同,可以分为2大块,即EEPROM和SRAM,那么,从某种意义上,我们可以把这个芯片作如下划分:

  • SRAM
  • 受保护的EEPROM(就是上面提到的)
  • 不受保护的EEPROM

当然受保护的EEPROM容量会小一些,不受保护的EEPROM容量大一些


 下面就开始说存放密码的区域了,也就是PWD区域

  • PWD,用于存放32位的密码
  • PACK,用于存放16位的Ack

显然这两个区域你是不可能通过手机去读的,DataSheet里面也写的很清楚

就是说你要是去读取这两个区域,读取的结果只能是返回全0。当然写是可以的,也就是刚刚上面提到的


 PT_I2C

这其实是一个Byte的简称,也就是那个位于SECTOR0的Page地址为E7H的第0个Byte,我们给他取名字叫做PT_I2C

PT_I2C里面的8位是这样的

这里主要关注一下SRAM_PORT这一位(如果我们要给某一bit取一个别名,就在名字后面加上_PORT这样,显然,SRAM_PORT就是和SRAM的控制相关的一个bit)

  • 0     不需要pass through模式的密码认证
  • 1     需要pass through模式的密码认证

当然了,从I2C角度来说,我们始终有这样的权限去读写:

  • 会话寄存器
  • SRAM
  • 包括PWD配置区域的配置页

PWD_AUTH

假设你现在手上有一个带有NFC功能的手机,接下来是如何实现认证的呢?

这里需要介绍一条非常重要的指令,也就是PWD_AUTH,如图所示

这条指令带一个参数,也就是你的输入密码

这样看太抽象了,我们不如看一下源代码,这是在发送指令

有意思的是,这个函数在整个Project中只用了一次,就是用在这个地方

authenticatePlus这个函数相当于在pwdAuth的基础上再封装了一层

那么哪些地方用到了authenticatePlus呢

很有意思的事情,我要去认证,我当然要先判断我自己现在的权限状态,那么如何去看自己的状态呢,居然是用一个static的变量,因此我对这个变量能否及时更新有所质疑

Android客户端中所有对于mAuthStatus的更新,都是通过这个函数获得的。mAuthStatus我个人认为你应该将他理解成为NXP芯片中的某个变量的影射,而不是一个Android客户端中的一个static变量!

显然这个的具体实现就是这个了,先挖坑,以后再说

    @Override
	public int getProtectionPlus() {
		try {
			reader.SectorSelect((byte) 0);
			byte[] auth0 = getAuth0Register();
			if(auth0 != null && auth0.length < 4) {
				try {
					readSRAMBlock();
					return AuthStatus.Protected_RW.getValue();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (FormatException e) {
					e.printStackTrace();
				}
				return AuthStatus.Protected_RW_SRAM.getValue();
			} else {
				if((auth0[3] & 0xFF) <= 0xEB) {
					byte[] access = getAccessRegister();
					byte[] pti2c = getPTI2CRegister();

					if (((0x0000080 & access[0]) >> Access_Offset.NFC_PROT.getValue() == 1) &&
							((0x0000004 & pti2c[0]) >> PT_I2C_Offset.SRAM_PROT.getValue() == 1)) {
						return AuthStatus.Protected_RW_SRAM.getValue();
					} else if (((0x0000080 & access[0]) >> Access_Offset.NFC_PROT.getValue() == 1)
					       && ((0x0000004 & pti2c[0]) >> PT_I2C_Offset.SRAM_PROT.getValue() == 0)) {
						return AuthStatus.Protected_RW.getValue();
					} else if (((0x0000080 & access[0]) >> Access_Offset.NFC_PROT.getValue() == 0)
						   && ((0x0000004 & pti2c[0]) >> PT_I2C_Offset.SRAM_PROT.getValue() == 1)) {
						return AuthStatus.Protected_W_SRAM.getValue();
					} else if (((0x0000080 & access[0]) >> Access_Offset.NFC_PROT.getValue() == 0)
						   && ((0x0000004 & pti2c[0]) >> PT_I2C_Offset.SRAM_PROT.getValue() == 0)) {
						return AuthStatus.Protected_W.getValue();
					}
				}
			}
			return AuthStatus.Unprotected.getValue();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (FormatException e) {
			e.printStackTrace();
		} catch (CommandNotSupportedException e) {
			e.printStackTrace();
		}

		// Check if the SRAM is lock
		try {
			readSRAMBlock();
			return AuthStatus.Protected_RW.getValue();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (FormatException e) {
			e.printStackTrace();
		}
		return AuthStatus.Protected_RW_SRAM.getValue();
	}

AUTHLIM

当然,为了防止暴力破解,用AuthLIM来表示最多可以尝试的次数,当开启后,他会自动记录下你的输入错误密码的次数,这个很简单,不多说了

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Android手机中使用OTG功能调试USB串口的Demo源码程序可在Android Studio中运行和调试。以下是一个简单的示例: 1. 首先,在MainActivity.java文件中创建一个类,用于处理与USB设备的通信。在该类中,你可以实现打开、关闭USB串口、发送和接收数据等功能。 ```java public class USBSerialCommunicator { private final Context mContext; private final UsbManager mUsbManager; private UsbDeviceConnection mConnection; private UsbSerialDevice mSerialDevice; private final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; public USBSerialCommunicator(Context context) { mContext = context; mUsbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); } public void openUSBSerialPort() { // 检查是否有连接的USB设备 HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList(); if (!deviceList.isEmpty()) { for (UsbDevice usbDevice : deviceList.values()) { // 检查USB设备是否有权限 PendingIntent permissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0); mUsbManager.requestPermission(usbDevice, permissionIntent); if (mUsbManager.hasPermission(usbDevice)) { mConnection = mUsbManager.openDevice(usbDevice); mSerialDevice = UsbSerialDevice.createUsbSerialDevice(usbDevice, mConnection); if (mSerialDevice != null) { if (mSerialDevice.open()) { mSerialDevice.setBaudRate(9600); mSerialDevice.setDataBits(UsbSerialInterface.DATA_BITS_8); mSerialDevice.setStopBits(UsbSerialInterface.STOP_BITS_1); mSerialDevice.setParity(UsbSerialInterface.PARITY_NONE); mSerialDevice.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF); // 设置串口数据接收监听器 mSerialDevice.read(mCallback); } } } } } } // 串口数据接收回调 private UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { @Override public void onReceivedData(byte[] bytes) { // 处理接收到的数据 } }; public void sendSerialData(byte[] data) { if (mSerialDevice != null) { mSerialDevice.write(data); } } public void closeUSBSerialPort() { if (mSerialDevice != null) { mSerialDevice.close(); mSerialDevice = null; } if (mConnection != null) { mConnection.close(); mConnection = null; } } } ``` 2. 接下来,在MainActivity.java文件中调用USBSerialCommunicator类的方法,以打开、关闭USB串口,并发送接收数据。 ```java public class MainActivity extends AppCompatActivity { private USBSerialCommunicator mUSBSerialCommunicator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mUSBSerialCommunicator = new USBSerialCommunicator(this); mUSBSerialCommunicator.openUSBSerialPort(); byte[] sendData = "Hello!".getBytes(); mUSBSerialCommunicator.sendSerialData(sendData); } @Override protected void onDestroy() { super.onDestroy(); mUSBSerialCommunicator.closeUSBSerialPort(); } } ``` 这是一个简单的示例,展示了如何使用OTG功能调试USB串口的Demo源码程序,并在Android Studio中进行运行和调试。你可以根据需要修改和扩展这个示例,以适应你的具体要求。 ### 回答2: 要在Android Studio上运行和调试OTG功能并调试USB串口的DEMO源码程序,您需要按照以下步骤操作: 1. 首先,确保您的Android手机具备OTG功能并且已经连接了OTG线。 2. 打开Android Studio,点击“File”菜单,选择“New”和“Import Project”选项,然后选择您存放DEMO源码程序的文件夹,点击“OK”导入项目。 3. 等待Android Studio完成项目导入后,找到并打开DEMO源码程序的主活动文件。 4. 检查源码程序中是否已经导入了OTG和USB串口的相关库文件,如果没有,请根据您的需要进行导入。 5. 在源码程序中找到与OTG功能有关的代码片段。这可能是检查设备是否具备OTG功能的代码或者检查OTG线连接状态的代码。 6. 如果没有相关的OTG功能代码,请按照Android开发文档中的指导添加OTG功能支持。 7. 找到与USB串口有关的代码片段。这可能是打开、关闭或者读写USB串口的代码。 8. 检查是否已经在项目的配置文件中申请了USB权限。如果没有,请添加以下权限到AndroidManifest.xml文件中: ```xml <uses-permission android:name="android.permission.USB_PERMISSION" /> ``` 9. 在源码程序中确保已经注册了USB的广播接收器。这个接收器将监听USB设备的插拔和权限相关的事件。 ```java private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if(device != null){ // 在此处进行串口设备的连接和操作 } } else { // 没有获得USB权限 } } } } }; ``` 10. 运行项目并调试。您可以使用虚拟设备或者在手机上运行源码程序,并使用日志输出等方式进行调试。 以上就是在Android Studio上运行和调试OTG功能并调试USB串口的DEMO源码程序的基本步骤。希望能对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值