如何判断SIM卡ICCID是否含额外十六进制位及处理末尾F字符
问题
读取SIM卡ICCID并与发货单列表比对时,发现部分卡片读取结果末尾多了"F"字符,与列表不符。需明确该字符含义、判断方法,以及是否可通过APDU命令处理。使用Delphi+Chilkat DLL的读取代码如下:
function TCardReader.ReadICCID(var Output: String): Boolean; var Success: Boolean; numBytes: Integer; bdRecv: HCkBinData; Buf: PWideChar; begin Success := self.ConnectCard; if Success then begin if CkSCard_getLastMethodSuccess(self.FScard) = True then begin bdRecv := CkBinData_Create(); //Select MF Success := self.SendCommand('A0A40000023F00', bdRecv); if Success then begin //Select ICCID Success := self.SendCommand('A0A40000022FE2', bdRecv); if Success then begin //Read the 10 bytes of ICCID EF Success := self.SendCommand('A0B000000A', bdRecv, Buf); if Success then Output := self.ByteToStrICCID(Buf); end; end; CkBinData_Dispose(bdRecv); end else Success := False; self.DisconnectCard; end; TLog.InfoLog('Read ICCID: ' + THelper.BoolToStr(Success)); result := Success; end;
读取结果示例:
8944501606231037754 8944501606231037345F
列表正确值:
8944501606231037754 8944501606231037345
解答
1. 末尾"F"字符的含义
该F是ICCID校验位的填充占位符。根据SIM卡规范,存储ICCID的EF(2FE2)文件固定为10字节,采用BCD编码(1字节对应2个字符),对应20位的ICCID结构:前19位是卡号主体,第20位是通过Luhn算法生成的校验位。部分运营商的SIM卡未写入有效校验位,而是用十六进制的F(二进制1111)填充该位置,因此读取后会出现末尾的F。
2. 判断卡片是否包含该额外位
- 长度+字符校验:读取到的ICCID如果是20位且最后一位为
F,即可判定存在该填充位; - 原始字节解析:读取EF(2FE2)的10字节原始数据,检查最后一个字节的低4位是否为
0xF,若是则为填充位而非有效校验位。
3. 处理方案
代码层面处理(推荐)
APDU命令无法直接过滤该填充位,因为EF(2FE2)的读取命令是按固定字节长度返回数据。最简便的方式是在代码中处理:
- 在
ByteToStrICCID函数中,判断转换后的字符串末尾是否为F,若是则截断最后一位; - 直接取转换后字符串的前19位(ICCID的核心识别部分是前19位,校验位仅用于验证,不影响卡号唯一性比对);
- 进阶处理:计算前19位的Luhn校验位,若最后一位不是计算出的有效数字(而是F),则截断末尾。
APDU命令调整(可选)
若要通过APDU减少返回数据,可将读取命令的长度参数改为09(读取9字节),即发送A0B0000009,但这样会得到18位字符,需额外解析第10字节的高4位来补全第19位,操作复杂度更高,不推荐。
内容的提问来源于stack exchange,提问作者Chaos
相关产品推荐
相关产品推荐

