
本示例使用的发卡器:https://item.taobao.com/item.htm?spm=a21dvs.23580594.0.0.47b32c1bXBkiRl&ft=t&id=615391857885
javascript
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Ntag 424 DNA标签读写</title>
<script language="javascript">
var iswsrun = false;
var ws;
var received_msg = "";
var mytimer;
var strls = "";
var errorno = "";
var ApduCommandStr = "";
var wsUri = "ws://127.0.0.1:39189"; //端口号必须与RFIDWebPlugin端口一致
function isHex(val) {
var testval = /^(\d|[A-F]|[a-f])+$/; // 十六进制数判断
return (testval.test(val));
}
function intToHex(num, len) {
return num.toString(16).padStart(len, '0');
}
function buttonDisable() { // 删除button 的 onclick 事件,防止重复执行指令
document.getElementById("butt_beep").setAttribute("onclick", null);
document.getElementById("butt_getdevnum").setAttribute("onclick", null);
document.getElementById("butt_getcardtype").setAttribute("onclick", null);
document.getElementById("butt_cpurequest1").setAttribute("onclick", null);
document.getElementById("butt_selectappid").setAttribute("onclick", null);
document.getElementById("butt_desfireauthkeyev2").setAttribute("onclick", null);
document.getElementById("butt_ntagchangkey").setAttribute("onclick", null);
document.getElementById("butt_ntagsetconfiguration").setAttribute("onclick", null);
document.getElementById("butt_forumtype4_write_ndeftag_uri").setAttribute("onclick", null);
document.getElementById("butt_forumtype4getuid").setAttribute("onclick", null);
document.getElementById("butt_forumtype4_read_ndeftag").setAttribute("onclick", null);
document.getElementById("butt_getcountervalue").setAttribute("onclick", null);
document.getElementById("butt_ntagreadfilesettings").setAttribute("onclick", null);
document.getElementById("butt_ntagchangefilesettings").setAttribute("onclick", null);
}
function beepDevice() { //驱动发卡器响声
returninfo.value = "";
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("pcdbeep,30");
}
function getdevicenumber() { //读取发卡器唯一出厂序号,可以当加密狗使用
returninfo.value = "";
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("pcdgetdevicenumber");
}
function geticcardtype() { //获取IC卡型号
returninfo.value = "";
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("getmifareversion");
}
function cpu_cpurequest1() { //激活发卡器感应区内的CPU卡,获取CPU卡卡号
returninfo.value = "";
carduid.value = "";
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("cpurequest1,");
}
function changeapp() {
switch (seleappid.selectedIndex) {
case 0:
selefileid.selectedIndex = 0;
selefci.selectedIndex = 0;
objedata.value = "D2 76 00 00 85 01 00";
break;
case 1:
selefileid.selectedIndex = 1;
selefci.selectedIndex = 0;
objedata.value = "3F 00";
break;
case 2:
selefileid.selectedIndex = 0;
selefci.selectedIndex = 0;
objedata.value = "D2 76 00 00 85 01 01";
break;
case 3:
selefileid.selectedIndex = 1;
selefci.selectedIndex = 0;
objedata.value = "E1 10";
break;
case 4:
selefileid.selectedIndex = 0;
selefci.selectedIndex = 1;
objedata.value = "A0 00 00 03 96 56 43 41 03 F0 15 40 00 00 00 0B";
break;
case 5:
selefileid.selectedIndex = 1;
selefci.selectedIndex = 0;
objedata.value = "DF 01";
break;
}
}
function selectappid() { //发送选择卡内应用的apdu指令
returninfo.value = "";
ApduCommandStr = "00A4";
if (selefileid.selectedIndex == 0) {
ApduCommandStr = ApduCommandStr + "04";
} else {
ApduCommandStr = ApduCommandStr + "00";
}
if (selefci.selectedIndex == 0) {
ApduCommandStr = ApduCommandStr + "00";
} else {
ApduCommandStr = ApduCommandStr + "0C";
}
objedatastr = objedata.value.replace(/\s/g, ""); //16进制的目标数据
if (!isHex(objedatastr) || (objedatastr.length % 2) != 0) {
textarea.value = "16进制目标数据输入错误,请输入正确的16进制目标数据!";
objedata.focus();
objedata.select();
return;
}
objedatalen = objedatastr.length / 2; //Lc数据长度
ApduCommandStr = ApduCommandStr + objedatalen.toString(16).padStart(2, '0') + objedatastr;
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("cpuisoapdu," + ApduCommandStr);
}
function desfireauthkeyev2() {
returninfo.value = "";
keyid = selectauthkey.selectedIndex; //认证密钥编号
keytype = selectdecnec.selectedIndex; //加解密方式
keylen = 32; //密钥长度
authkeystr = text_authkey.value.trim().replace(/\s+/g, ''); //16进制的认证密钥
if (!isHex(authkeystr) || authkeystr.length != keylen) {
alert("认证密钥输入错误,请输入正确的16进制认证密钥!");
text_authkey.focus();
text_authkey.select();
return;
}
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("desfireauthkeyev2," + authkeystr + "," + keyid + "," + keytype);
}
function ntagchangkey() {
returninfo.value = "";
keyid = selectnewkey.selectedIndex; //需要更改的密钥编号
keylen = 32; //密钥长度
newkeystr = text_newkey.value.trim().replace(/\s+/g, ''); //16进制的新密钥
if (!isHex(newkeystr) || newkeystr.length != keylen) {
alert("新密钥输入错误,请输入正确的16进制新密钥!");
text_newkey.focus();
text_newkey.select();
return;
}
authkeystr = text_authkey.value.trim().replace(/\s+/g, ''); //16进制的认证密钥
if (!isHex(authkeystr) || authkeystr.length != keylen) {
alert("认证密钥输入错误,请输入正确的16进制认证密钥!");
text_authkey.focus();
text_authkey.select();
return;
}
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("ntagchangkey," + newkeystr + "," + keyid + ",1," + authkeystr);
}
function ntagsetconfiguration() {
returninfo.value = "";
var answer = confirm("424卡更改为随机UID模式后,此卡将永久为随机模式,此操作不可逆!确定要继续将卡更改为随机UID模式吗?");
if (answer) { }
else {
return;
}
optionval = 0; //操作代码
setbuff = "02"; //16进制的设置参数,00为固定UID,02为动态UID,特别警告,改为02后卡将会锁死这个序设定值,再也不能改回固定UID
bufflen = 1; //参数长度
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("ntagsetconfiguration," + optionval + "," + setbuff + "," + bufflen);
}
function examples1() {
text_title.value = "百度";
select_prefix.selectedIndex = 1;
text_uri.value = "baidu.com?uid=00000000000000000000000000000000";
select_SetCommMode.selectedIndex = 0; //通讯模式为明文
select_readonlykey.selectedIndex = 5; //只读指令需要先认证的密钥
select_writeonlykey.selectedIndex = 5; //只写指令需要先认证的密钥
select_readwritekey.selectedIndex = 5; //读写指令需要先认证的密钥
select_changesetkey.selectedIndex = 0; //更改设置指令需要先认证的密钥
select_SDMRead.selectedIndex = 0; //SDM元数据读取访问权限
select_CMACCalc.selectedIndex = 5; //CMAC计算的派生密钥
select_SDMCount.selectedIndex = 6; //SDM计数器检索密钥
check_SDMMirrorImageEn.checked = true; //启用SDM镜像
check_UIDMirrorImageEn.checked = true; //启用UID镜像
check_CounMirrorImageEn.checked = false; //启用计数器镜像
check_CounLimitEn.checked = false; //启用计数器限额
check_SDMENCFileData.checked = false; //check_SDMENCFileData
text_UIDMirrorImage.value = 0; //UID镜像位置
text_PICCDataOffset.value = 26; //PICCDataOffset
text_SDMMACInputOffset.value = 0;
text_SDMMACoffset.value = 0;
text__Counoffset.value = 0; //计数器数据位置
text_CounLimit.value = 0; //计数器限额值
text_SDMENCOffset.value = 0;
text_SDMENCLength.value = 0;
}
function examples2() {
text_title.value = "百度";
select_prefix.selectedIndex = 1;
text_uri.value = "baidu.com?uid=00000000000000x000000";
select_SetCommMode.selectedIndex = 0; //通讯模式为明文
select_readonlykey.selectedIndex = 5; //只读指令需要先认证的密钥
select_writeonlykey.selectedIndex = 5; //只写指令需要先认证的密钥
select_readwritekey.selectedIndex = 5; //读写指令需要先认证的密钥
select_changesetkey.selectedIndex = 0; //更改设置指令需要先认证的密钥
select_SDMRead.selectedIndex = 5; //SDM元数据读取访问权限
select_CMACCalc.selectedIndex = 5; //CMAC计算的派生密钥
select_SDMCount.selectedIndex = 5; //SDM计数器检索密钥
check_SDMMirrorImageEn.checked = true; //启用SDM镜像
check_UIDMirrorImageEn.checked = true; //启用UID镜像
check_CounMirrorImageEn.checked = true; //启用计数器镜像
check_CounLimitEn.checked = false; //启用计数器限额
check_SDMENCFileData.checked = false; //check_SDMENCFileData
text_UIDMirrorImage.value = 26; //UID镜像位置
text_PICCDataOffset.value = 0; //PICCDataOffset
text_SDMMACInputOffset.value = 0;
text_SDMMACoffset.value = 0;
text__Counoffset.value = 41; //计数器数据位置
text_CounLimit.value = 0; //计数器限额值
text_SDMENCOffset.value = 0;
text_SDMENCLength.value = 0;
}
function examples3() {
text_title.value = "";
select_prefix.selectedIndex = 1;
text_uri.value = "baidu.com?picc_data=00000000000000000000000000000000&e=12345678901234560000000000000000&cmac=0000000000000000";
select_SetCommMode.selectedIndex = 0; //通讯模式为明文
select_readonlykey.selectedIndex = 5; //只读指令需要先认证的密钥
select_writeonlykey.selectedIndex = 5; //只写指令需要先认证的密钥
select_readwritekey.selectedIndex = 5; //读写指令需要先认证的密钥
select_changesetkey.selectedIndex = 0; //更改设置指令需要先认证的密钥
select_SDMRead.selectedIndex = 0; //SDM元数据读取访问权限
select_CMACCalc.selectedIndex = 0; //CMAC计算的派生密钥
select_SDMCount.selectedIndex = 0; //SDM计数器检索密钥
check_SDMMirrorImageEn.checked = true; //启用SDM镜像
check_UIDMirrorImageEn.checked = true; //启用UID镜像
check_CounMirrorImageEn.checked = true; //启用计数器镜像
check_CounLimitEn.checked = false; //启用计数器限额
check_SDMENCFileData.checked = true; //check_SDMENCFileData
text_UIDMirrorImage.value = 0; //UID镜像位置
text_PICCDataOffset.value = 27; //PICCDataOffset
text_SDMMACInputOffset.value = 62;
text_SDMMACoffset.value = 100;
text__Counoffset.value = 0; //计数器数据位置
text_CounLimit.value = 0; //计数器限额值
text_SDMENCOffset.value = 62;
text_SDMENCLength.value =32;
}
function getCaretPos() {
Cursoroffset = 7 + text_uri.selectionStart;
if (text_title.value.length > 0) {
Cursoroffset = Cursoroffset + 5;
}
text_selestar.value = Cursoroffset;
}
function forumtype4_write_ndeftag_uri() {
returninfo.value = "";
titlestr = text_title.value.trim(); //标题
uriheader = String(select_prefix.selectedIndex); //前缀
uriinfo = text_uri.value; //uri链接
myctrlword = 0; //写卡不需要认证卡片密钥
picckey = "";
if (check_RWAuthKey.checked) { //AES-128密文+MAC模式 认证写卡
myctrlword = 64;
if (select_RWCommMode.selectedIndex == 2) {
myctrlword = myctrlword + 3; //bit1-0为3表示通信模式为密文+MAC模式
}else{
if (select_RWCommMode.selectedIndex == 1) {
myctrlword = myctrlword + 1; //bit1-0为1表示通信模式为MAC,
}
}
picckey = "04"; //AES,用71指令认证
picckey = picckey + select_RWAuthKeyId.selectedIndex.toString(16).padStart(2, '0'); //认证密钥编号
authkeystr = text_RWauthkey.value.trim().replace(/\s+/g, ''); //16进制的认证密钥
if (!isHex(authkeystr) || authkeystr.length != 32) {
alert("认证密钥输入错误,请输入正确的16进制认证密钥!");
text_RWauthkey.focus();
text_RWauthkey.select();
return;
}
picckey = picckey + authkeystr;
}
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("forumtype4_write_ndeftag," + titlestr + "," + uriheader + "," + uriinfo + "," + myctrlword + "," + picckey);
}
function forumtype4getuid() {
returninfo.value = "";
picckey = "04"; //AES,用71指令认证
picckey = picckey + select_RWAuthKeyId.selectedIndex.toString(16).padStart(2, '0'); //认证密钥编号
authkeystr = text_RWauthkey.value.trim().replace(/\s+/g, ''); //16进制的认证密钥
if (!isHex(authkeystr) || authkeystr.length != 32) {
alert("认证密钥输入错误,请输入正确的16进制认证密钥!");
text_RWauthkey.focus();
text_RWauthkey.select();
return;
}
picckey = picckey + authkeystr;
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("forumtype4getuid," + picckey);
}
function forumtype4_read_ndeftag() {
returninfo.value = "";
if (check_RWAuthKey.checked) { //AES-128密文+MAC模式 认证读卡
if (select_RWCommMode.selectedIndex == 2) {
myctrlword = myctrlword + 3; //bit1-0为3表示通信模式为密文+MAC模式
} else {
if (select_RWCommMode.selectedIndex == 1) {
myctrlword = myctrlword + 1; //bit1-0为1表示通信模式为MAC,
}
}
picckey = "04"; //AES,用71指令认证
picckey = picckey + select_RWAuthKeyId.selectedIndex.toString(16).padStart(2, '0'); //认证密钥编号
authkeystr = text_RWauthkey.value.trim().replace(/\s+/g, ''); //16进制的认证密钥
if (!isHex(authkeystr) || authkeystr.length != 32) {
alert("认证密钥输入错误,请输入正确的16进制认证密钥!");
text_RWauthkey.focus();
text_RWauthkey.select();
return;
}
myctrlword = 64;
picckey = picckey + authkeystr;
keylen = 18;
} else {
myctrlword = 0; //读卡不需要认证卡片密钥
picckey = "000000000000000000000000000000000000"; //18字节占位符
keylen = 0; //密钥长度
}
if (check_AnalyzeImage.checked) { //解析镜像
sdmkeystr = text_SDMkey.value.trim().replace(/\s+/g, ''); //16进制的SDM解析密钥
if (!isHex(sdmkeystr) || sdmkeystr.length != 32) {
alert("SDM解析密钥输入错误,请输入正确的16进制SDM解析密钥!");
text_SDMkey.focus();
text_SDMkey.select();
return;
}
picckey = picckey + sdmkeystr;
cmackeystr = text_CMACkey.value.trim().replace(/\s+/g, ''); //16进制的CMAC验证密钥
if (!isHex(cmackeystr) || cmackeystr.length != 32) {
alert("CMAC验证密钥输入错误,请输入正确的16进制CMAC验证密钥!");
text_CMACkey.focus();
text_CMACkey.select();
return;
}
myctrlword = myctrlword + 4;
picckey = picckey + cmackeystr;
keylen = 50;
}
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("forumtype4_read_ndeftag," + myctrlword + "," + keylen + "," + picckey);
}
function getcountervalue() {
returninfo.value = "";
ApduCommandStr = "90F60000010200";
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("cpuisoapdu," + ApduCommandStr);
}
function ntagreadfilesettings() {
returninfo.value = "";
text_setup.value = "";
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("ntagreadfilesettings," + select_RWsetconnmodel.selectedIndex + ",2"); //2号文件为NDEF文件默认通信模式为明文,3号普通数据文件为默认通信模式为密文+MAC保护,1号文件 是CC文件)
}
function ntagchangefilesettings() {
returninfo.value = "";
const settingsbuf = new Uint8Array(32);
if (select_SetCommMode.selectedIndex == 1) {
settingsbuf[0] = 0x01; //MAC保护
} else {
if (select_SetCommMode.selectedIndex == 2) {
settingsbuf[0] = 0x03; //密文+MAC保护
} else { settingsbuf[0] = 0x00; } //明文
}
if (check_SDMMirrorImageEn.checked) {
settingsbuf[0] = settingsbuf[0]+0x40; //启用SDM镜像
}
if (select_changesetkey.selectedIndex < 5) { //更改指令 需要先认证的密码
settingsbuf[1] = select_changesetkey.selectedIndex;
} else {
if (select_changesetkey.selectedIndex == 5) {
settingsbuf[1] = 0x0e; //无需密码,直接用明文
} else { settingsbuf[1] = 0x0f; } //禁止该指令
}
if (select_readwritekey.selectedIndex < 5) { //读写指令 需要先认证的密码
settingsbuf[1] = settingsbuf[1] + select_readwritekey.selectedIndex *16;
} else {
if (select_readwritekey.selectedIndex == 5) {
settingsbuf[1] = settingsbuf[1]+ 0xe0; //无需密码,直接用明文
} else { settingsbuf[1] = settingsbuf[1] + 0xf0; } //禁止该指令
}
if (select_writeonlykey.selectedIndex < 5) { //只写指令 需要先认证的密码
settingsbuf[2] = select_writeonlykey.selectedIndex;
} else {
if (select_writeonlykey.selectedIndex == 5) {
settingsbuf[2] = 0x0e; //无需密码,直接用明文
} else { settingsbuf[2] = 0x0f; } //禁止该指令
}
if (select_readonlykey.selectedIndex < 5) { //只读指令 需要先认证的密码
settingsbuf[2] = settingsbuf[2] + select_readonlykey.selectedIndex * 16;
} else {
if (select_readonlykey.selectedIndex == 5) {
settingsbuf[2] = settingsbuf[2] + 0xe0; //无需密码,直接用明文
} else { settingsbuf[2] = settingsbuf[2] + 0xf0; } //禁止该指令
}
j = 3;
if ((settingsbuf[0] & 0x40) > 0) { //已经启用SDM镜像
settingsbuf[3] = 0x01;
if (check_UIDMirrorImageEn.checked) {
settingsbuf[3] = settingsbuf[3] + 0x80; //启用UID镜像
}
if (check_CounMirrorImageEn.checked) {
settingsbuf[3] = settingsbuf[3] + 0x40; //启用计数器镜像
}
if (check_CounLimitEn.checked) {
settingsbuf[3] = settingsbuf[3] + 0x20; //启用计数器限额
}
if (check_SDMENCFileData.checked) {
settingsbuf[3] = settingsbuf[3] + 0x10; //启用SDMENCFileData
}
settingsbuf[4] = 0xf0;
if (select_SDMCount.selectedIndex < 5) { //计数器访问 需要先认证的密码
settingsbuf[4] = settingsbuf[4] + select_SDMCount.selectedIndex ;
} else {
if (select_SDMCount.selectedIndex == 5) {
settingsbuf[4] = settingsbuf[4] + 0x0e; //无需密码,直接用明文
} else { settingsbuf[4] = settingsbuf[4] + 0x0f; } //禁止该指令
}
if (select_SDMRead.selectedIndex < 5) { //SDMMetaRead 需要先认证的密码
settingsbuf[5] = select_SDMRead.selectedIndex * 16;
} else {
if (select_SDMRead.selectedIndex == 5) {
settingsbuf[5] = 0xe0; //无需密码,直接用明文
} else { settingsbuf[5] = 0xf0; } //禁止该指令
}
j = j + 1;
if (select_CMACCalc.selectedIndex < 5) { //CMAC计算派生 需要先认证的密码
settingsbuf[5] = settingsbuf[5] + select_CMACCalc.selectedIndex;
} else {
settingsbuf[5] = settingsbuf[5] + 0x0f; //禁止该指令
}
j = 6;
if ((settingsbuf[5] & 0xf0) == 0xe0) {
if ((settingsbuf[3] & 0x80) > 0) { //UID镜像位置
longi = text_UIDMirrorImage.value;
settingsbuf[6] = longi;
settingsbuf[7] = longi / 256;
settingsbuf[8] = longi / 65536;
j = 9;
}
if ((settingsbuf[3] & 0x40) > 0) { //计数器镜像
longi = text__Counoffset.value;
settingsbuf[j] = longi;
settingsbuf[j+1] = longi / 256;
settingsbuf[j+2] = longi / 65536;
j = j+3;
}
} else {
if ((settingsbuf[5] & 0xf0) < 0x50) {
longi = text_PICCDataOffset.value; //ENCPICCDataOffset(UID和随机数加密后的数据位置)
settingsbuf[6] = longi;
settingsbuf[7] = longi / 256;
settingsbuf[8] = longi / 65536;
j = 9;
}
}
if ((settingsbuf[5] & 0x0f) != 0x0f) {
longi = text_SDMMACInputOffset.value; //SDMMACInputOffset
settingsbuf[j] = longi;
settingsbuf[j + 1] = longi / 256;
settingsbuf[j + 2] = longi / 65536;
j = j + 3;
if ((settingsbuf[3] & 0x10) > 0x00) {
longi = text_SDMENCOffset.value; //SDMENCOffset
settingsbuf[j] = longi;
settingsbuf[j + 1] = longi / 256;
settingsbuf[j + 2] = longi / 65536;
j = j + 3;
longi = text_SDMENCLength.value; //SDMENCLength
settingsbuf[j] = longi;
settingsbuf[j + 1] = longi / 256;
settingsbuf[j + 2] = longi / 65536;
j = j + 3;
}
longi = text_SDMMACoffset.value; //SDMMACOffset
settingsbuf[j] = longi;
settingsbuf[j + 1] = longi / 256;
settingsbuf[j + 2] = longi / 65536;
j = j + 3;
}
if ((settingsbuf[3] & 0x20) > 0x00) {
longi = text_CounLimit.value; //计数器限额值
settingsbuf[j] = longi;
settingsbuf[j + 1] = longi / 256;
settingsbuf[j + 2] = longi / 65536;
j = j + 3;
}
}
//参数设定规则校验------------------------------------------------------
if ((settingsbuf[0] & 0x40) > 0x00) { //已经启用SDM镜像
if ((settingsbuf[3] & 0xc0) == 0x00) {
alert("当开启SDM镜像时,必须开启UID镜像或计数器镜像!");
return;
}
if ((settingsbuf[3] & 0x80) > 0x00) { //已经启用UID镜像
if ((settingsbuf[5] & 0xf0) == 0xf0) {
alert("当启用UID镜像时,SDM元数据读取访问权限不能为禁止!");
return;
}
} else {
if ((settingsbuf[5] & 0xf0) < 0xf0) {
alert("当不开启UID镜像时,SDM元数据读取访问权限只能为禁止!");
return;
}
}
if ((settingsbuf[3] & 0x40) == 0x00) { //当不开启计数器镜像时
if ((settingsbuf[4] & 0x0f) < 0x0f) {
alert("当不开启计数器镜像时,SDM计数器检索密钥只能为禁止!");
return;
}
}
if (((settingsbuf[3] & 0x80) > 0x00) | ((settingsbuf[5] & 0xf0) < 0x50)) {
i = 9; //存在UIDOffset或PICCDataOffset
} else { i = 6;}
if (settingsbuf[5] == 0xe0) {
i = i + 3; //SDMReadCtrOffset存在
}
if ((settingsbuf[5] & 0x0f) < 0x05) { //SDMFileRead access right
SDMMACInputOffset = settingsbuf[i] + settingsbuf[i + 1] * 256 + settingsbuf[i + 2] * 65536;
i = i + 3;
if ((settingsbuf[3] & 0x10) > 0x00) { //SDMENCFileData
SDMENCOffset = settingsbuf[i] + settingsbuf[i + 1] * 256 + settingsbuf[i + 2] * 65536;
i = i + 3;
SDMENCLength = settingsbuf[i] + settingsbuf[i + 1] * 256 + settingsbuf[i + 2] * 65536;
i = i + 3;
}
SDMMACOffset = settingsbuf[i] + settingsbuf[i + 1] * 256 + settingsbuf[i + 2] * 65536;
i = i + 3;
if ((settingsbuf[3] & 0x10) > 0x00) { //SDMENCFileData
if (SDMENCOffset < SDMMACInputOffset) {
alert("SDMENCOffset不能小于SDMMACInputOffset!");
return;
}
if (SDMENCLength < 32) {
alert("SDMENCLength不能小于32!");
return;
}
if (SDMMACOffset < (SDMENCOffset + SDMENCLength)) {
alert("SDMMACOffset不能小于(SDMENCOffset + SDMENCLength)!");
return;
}
} else {
if(SDMMACOffset < SDMMACInputOffset){
alert("SDMMACOffset不能小于SDMMACInputOffset!");
return;
}
}
}
}
//------------------------------------------------------------------------------------------------------------
setdatahex = "";
for (i = 0; i < j; i++) {
setdatahex = setdatahex + settingsbuf[i].toString(16).padStart(2, '0').toUpperCase();
}
text_setup.value = setdatahex;
buttonDisable(); //删除按键的 onclick 事件,防止重复执行指令
WebSocketRun("ntagchangefilesettings," + select_RWsetconnmodel.selectedIndex + ",2," + setdatahex + "," + j); //2号文件为NDEF文件默认通信模式为明文,3号普通数据文件为默认通信模式为密文+MAC保护,1号文件 是CC文件)
}
function ButtonEnabled() { //恢复各button 的onclick事件
document.getElementById("butt_beep").setAttribute("onclick", "beepDevice()");
document.getElementById("butt_getdevnum").setAttribute("onclick", "getdevicenumber()");
document.getElementById("butt_getcardtype").setAttribute("onclick", "geticcardtype()");
document.getElementById("butt_cpurequest1").setAttribute("onclick", "cpu_cpurequest1()");
document.getElementById("butt_selectappid").setAttribute("onclick", "selectappid()");
document.getElementById("butt_desfireauthkeyev2").setAttribute("onclick", "desfireauthkeyev2()");
document.getElementById("butt_ntagchangkey").setAttribute("onclick", "ntagchangkey()");
document.getElementById("butt_ntagsetconfiguration").setAttribute("onclick", "ntagsetconfiguration()");
document.getElementById("butt_forumtype4_write_ndeftag_uri").setAttribute("onclick", "forumtype4_write_ndeftag_uri()");
document.getElementById("butt_forumtype4getuid").setAttribute("onclick", "forumtype4getuid()");
document.getElementById("butt_forumtype4_read_ndeftag").setAttribute("onclick", "forumtype4_read_ndeftag()");
document.getElementById("butt_getcountervalue").setAttribute("onclick", "getcountervalue()");
document.getElementById("butt_ntagreadfilesettings").setAttribute("onclick", "ntagreadfilesettings()");
document.getElementById("butt_ntagchangefilesettings").setAttribute("onclick", "ntagchangefilesettings()");
}
function DispErrInfo(Errcode) {
var errstr = "";
switch (Errcode) {
case "ReturnCode:001":
errstr = ",读写扇区数据失败!";
break;
case "ReturnCode:002":
errstr = ",读写1、2块数据失败!";
break;
case "ReturnCode:003":
errstr = ",请先激活CPU卡再继续操作!";
break;
case "ReturnCode:008":
errstr = ",未寻到卡,请将卡放到发卡器的感应区!";
break;
case "ReturnCode:009":
errstr = ",有多张卡在感应区,寻卡过程中防冲突失败,读卡失败!";
break;
case "ReturnCode:010":
errstr = ",该卡可能已被休眠,无法选中卡片!";
break;
case "ReturnCode:011":
errstr = ",密码装载失败!";
break;
case "ReturnCode:012":
errstr = ",卡密码认证失败!";
break;
case "ReturnCode:013":
errstr = ",读块操作失败,原因是刷卡太快或本块所对应的区还没通过密码认证!";
break;
case "ReturnCode:014":
errstr = ",写块操作失败,原因是刷卡太快或本块所对应的区还没通过密码认证!";
break;
case "ReturnCode:018":
errstr = ",写块操作失败!";
break;
case "ReturnCode:021":
errstr = ",没有动态库!";
break;
case "ReturnCode:022":
errstr = ",动态库或驱动程序异常!";
break;
case "ReturnCode:023":
errstr = ",驱动程序错误或发卡器未连接!";
break;
case "ReturnCode:024":
errstr = ",操作超时,一般是动态库没有反映!";
break;
case "ReturnCode:025":
errstr = ",发送字数不够!";
break;
case "ReturnCode:026":
errstr = ",发送的CRC错!";
break;
case "ReturnCode:027":
errstr = ",接收的字数不够!";
break;
case "ReturnCode:028":
errstr = ",接收的CRC错!";
break;
case "ReturnCode:029":
errstr = ",函数输入参数格式错误!";
break;
case "ReturnCode:041":
errstr = ",写文件失败,请检查通信模式是否正确!";
break;
case "ReturnCode:045":
errstr = ",此卡不支持更改UID号或UID块已被锁定!";
break;
case "ReturnCode:046":
errstr = ",信息过大,标签容量不足!";
break;
case "ReturnCode:047":
errstr = ",读文件失败,请检查通信模式是否正确!";
break;
case "ReturnCode:050":
errstr = ",RATS错误,厂家调试代码,用户不需理会!";
break;
case "ReturnCode:051":
errstr = ",PPS错误,厂家调试代码,用户不需理会!";
break;
case "ReturnCode:052":
errstr = ",已进入了14443-4协议状态,可进行CPU卡功能所有操作!";
break;
case "ReturnCode:053":
errstr = ",未寻到卡,请将卡放到发卡器的感应区!";
break;
case "ReturnCode:054":
errstr = ",CPU卡功能通讯错误!";
break;
case "ReturnCode:055":
errstr = ",发送ACK指令给卡,让卡接着发送数据回来!";
break;
case "ReturnCode:056":
errstr = ",清空根目录失败!";
break;
case "ReturnCode:057":
errstr = ",卡片不支持Forum_Type4协议,请先认证打勾选中"需要认证密码再写入"再试,如果还有此提示,可能该卡不是Forum_Type4_Tag卡!";
break;
case "ReturnCode:058":
errstr = ",卡片初始化失败!";
break;
case "ReturnCode:059":
errstr = ",分配的空间不足!";
break;
case "ReturnCode:060":
errstr = ",本次操作的实体已存在!";
break;
case "ReturnCode:061":
errstr = ",无足够空间!";
break;
case "ReturnCode:062":
errstr = ",文件不存在!";
break;
case "ReturnCode:063":
errstr = ",权限不足,有可能是用只读密码认证,导致无法更改读写密码或无法写文件!";
break;
case "ReturnCode:064":
errstr = ",密码不存在,或密钥文件未创建!";
break;
case "ReturnCode:065":
errstr = ",传送长度错误!";
break;
case "ReturnCode:066":
errstr = ",接收长度错误,即接收的数据长度指定过大!";
break;
case "ReturnCode:067":
errstr = ",功能不支持、或卡中无MF、或卡片已锁定!";
break;
case "ReturnCode:068":
errstr = ",密码认证错识次数过多,该密码已被锁死!";
break;
case "ReturnCode:070":
case "ReturnCode:071":
case "ReturnCode:072":
case "ReturnCode:073":
case "ReturnCode:074":
case "ReturnCode:075":
case "ReturnCode:076":
case "ReturnCode:077":
case "ReturnCode:078":
case "ReturnCode:079":
case "ReturnCode:080":
case "ReturnCode:081":
case "ReturnCode:082":
case "ReturnCode:083":
case "ReturnCode:084":
case "ReturnCode:085":
var lastnum = Errcode.substring(Errcode.lenth - 2, 2) - 70;
errstr = ",密码错误,剩余次数为:" + lastnum + ",如剩余次数为0,该密码将锁死,无法再认证!";
break;
case "ReturnCode:086":
errstr = ",更改后的密码长度必须和创建时的长度一致!";
break;
case "ReturnCode:087":
errstr = ",应用目录不存在!";
break;
case "ReturnCode:088":
errstr = ",应用文件不存在!";
break;
case "ReturnCode:089":
errstr = ",文件号不能超过 5 !";
break;
case "ReturnCode:090":
errstr = ",读取文件时返回的长度不足,数据可能不正确!";
break;
case "ReturnCode:091":
errstr = ",一次读文件的长度不能超过255 !";
break;
case "ReturnCode:092":
errstr = ",一次写文件的长度不能超过247 !";
break;
case "ReturnCode:444":
errstr = ",RFIDWebPlugin系统文件错误!";
break;
case "ReturnCode:555":
errstr = ",未发现有效的NFC标签!";
break;
default:
errstr = ",未知的错误!";
}
return errstr;
}
function ReturnCodeDes(ReturnCode) {
var infostr = "";
ReturnCode = ReturnCode.replace(/\s+/g, '');
if (ReturnCode.slice(0, 3) == "63C") {
} else {
switch (ReturnCode) {
case "9000":
infostr = "成功!";
break;
case "9100":
infostr = "成功!";
break;
case "6281":
infostr = "回送的数据可能错误!";
break;
case "6283":
infostr = "选择文件无效,文件或密钥校验错误!";
break;
case "6400":
infostr = "状态标志未改变!";
break;
case "6581":
infostr = "写EEPROM 不成功!";
break;
case "6700":
infostr = "长度错误!";
break;
case "6900":
infostr = "CLA 与线路保护要求不匹配!";
break;
case "6901":
infostr = "无效的状态!";
break;
case "6981":
infostr = "命令与文件结构不相容!";
break;
case "6982":
infostr = "不满足安全状态!";
break;
case "6983":
infostr = "密钥被锁死!";
break;
case "6984":
infostr = "MAC格式不符合!";
break;
case "6985":
infostr = "使用条件不满足!";
break;
case "6986":
infostr = "请先选择文件!";
break;
case "6987":
infostr = "无安全报文!";
break;
case "6988":
infostr = "安全报文数据项不正确!";
break;
case "6A80":
infostr = "数据域参数错误!";
break;
case "6A81":
infostr = "功能不支持或卡中无MF 或卡片已锁定!";
break;
case "6A82":
infostr = "文件未找到!";
break;
case "6A83":
infostr = "记录未找到!";
break;
case "6A84":
infostr = "文件无足够空间!";
break;
case "6A86":
infostr = "参数P1 P2 错误!";
break;
case "6A88":
infostr = "密钥未找到!";
break;
case "6B00":
infostr = "状态标志未改变在达到Le/Lc 字节之前文件结束,偏移量错误!";
break;
case "6E00":
infostr = "无效的CLA!";
break;
case "6F00":
infostr = "数据无效!";
break;
case "9302":
infostr = "MAC 错误!";
break;
case "9303":
infostr = "应用已被锁定!";
break;
case "9401":
infostr = "金额不足!";
break;
case "9403":
infostr = "密钥未找到!";
break;
case "9406":
infostr = "所需的MAC 不可用!";
break;
case "91AE":
infostr = "认证失败,请检查命行的参数和前期计算是否错误!";
break;
case "91CA":
infostr = "上一个命令未完全完成!";
break;
case "917E":
infostr = "指令长度错误,如果上一条操作为密码认证,本次指令必需用密文+MAC保护的通信模式,否则用明文的通信模式";
break;
case "9140":
infostr = "当前目录或应用密钥不存在,请先选择正确的目录或应用!";
break;
case "919D":
infostr = "处于未验证密码的状态,该指令无法操作!";
break;
case "911E":
infostr = "MAC错误!";
break;
case "91F0":
infostr = "该文件号不存在!";
break;
case "919E":
infostr = "参数无效!";
break;
case "91BE":
infostr = "试图读取/写入的数据超出文件/记录的边界!";
break;
case "91A0":
infostr = "请求的 AID 不存在!";
break;
case "910C":
infostr = "备份文件不改变,不需要CommitTransaction和AbortTransaction!";
break;
default:
infostr = "未知的状态!";
}
}
return infostr;
}
window.onerror = function (e) { //异常提示
ButtonEnabled(); //恢复按键的onclick事件
alert("不好意思,出错了!");
return true; //屏蔽系统事件
}
function timeoutevent() { //websockket通讯超时
ws.close();
returninfo.value = "websockket返回超时";
ButtonEnabled(); //恢复按键的onclick事件
}
function WebSocketRev(evt) { //websockket数据处理
clearTimeout(mytimer);
received_msg = evt.data;
ws.close();
//在这里解析返回数据
var strlist = received_msg.split(",");
if (strlist.length > 1) {
var dispstr = "";
switch (strlist[0]) {
case "pcdbeep":
dispstr = "函数名称:" + strlist[0] + "\r\n";
if (strlist[1] == "ReturnCode:000") {
dispstr = dispstr + "操作结果:" + strlist[1] + ",已执行蜂鸣响声操作!\r\n"
} else {
dispstr = dispstr + "操作结果:" + strlist[1] + DispErrInfo(strlist[1]);
}
returninfo.value = dispstr;
break;
case "pcdgetdevicenumber":
dispstr = "函数名称:" + strlist[0] + "\r\n";
if (strlist[1] == "ReturnCode:000") {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + ",已读取设备编号!\r\n";
} else {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + DispErrInfo(strlist[1]);
}
if (strlist.length > 2) {
dispstr = dispstr + "设备编号:" + strlist[2] + "\r\n";
}
returninfo.value = dispstr;
break;
case "getmifareversion":
dispstr = "函数名称:" + strlist[0] + "\r\n";
if (strlist[1] == "ReturnCode:000") {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + ",读取IC卡型号成功!\r\n";
dispstr = dispstr + "ATQA:" + strlist[2] + "\r\n";
dispstr = dispstr + "SAK:" + strlist[3] + "\r\n";
dispstr = dispstr + "型号:" + strlist[4] + "\r\n";
} else {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + DispErrInfo(strlist[1]);
}
if (strlist.length > 5) {
dispstr = dispstr + "Version:" + strlist[5] + "\r\n";
}
returninfo.value = dispstr;
break;
case "cpurequest1":
dispstr = "函数名称:" + strlist[0] + "\r\n";
if (strlist[1] == "ReturnCode:000" || strlist[1] == "ReturnCode:052") {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + ",卡已激活!\r\n";
dispstr = dispstr + "16进制卡号:" + strlist[2] + "\r\n";
dispstr = dispstr + "10进制卡号:" + strlist[3] + "\r\n";
dispstr = dispstr + "卡片参数:" + strlist[4] + "\r\n";
dispstr = dispstr + "卡片版本:" + strlist[5] + "\r\n";
dispstr = dispstr + "厂家代码:" + strlist[6] + "\r\n";
if (strlist.length > 8) {
dispstr = dispstr + "ATQA:" + strlist[7] + "\r\n";
dispstr = dispstr + "SAK:" + strlist[8] + "\r\n";
}
carduid.value = strlist[2];
} else {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + DispErrInfo(strlist[1]);
}
returninfo.value = dispstr;
break;
case "cpuisoapdu":
dispstr = "函数名称:" + strlist[0] + "\r\n";
if (strlist[1] == "ReturnCode:000") {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + ",返回代码:" + strlist[2];
dispstr = dispstr + ",代码说明:" + ReturnCodeDes(strlist[2]);
} else {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + DispErrInfo(strlist[1]);
}
returninfo.value = dispstr;
break;
case "desfireauthkeyev2":
dispstr = "执行函数名称:" + strlist[0] + " 认证标签密钥操作\r\n";
if (strlist[1] == "ReturnCode:000") {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + ",返回代码:" + strlist[2];
dispstr = dispstr + ",代码说明:" + ReturnCodeDes(strlist[2]);
} else {
dispstr = dispstr + "操作结果:" + strlist[1];
dispstr = dispstr + ",返回代码:" + strlist[2];
dispstr = dispstr + ",代码说明:" + ReturnCodeDes(strlist[2]);
if (strlist[2] == "9140") {
dispstr = dispstr + ",NTAG424卡建议选择上面的 【424卡的ISO DF Name】后执行【第二步:选择应用】后再认证。";
}
}
returninfo.value = dispstr;
break;
case "ntagchangkey":
dispstr = "执行函数名称:" + strlist[0] + " 更改标签密钥操作\r\n";
dispstr = dispstr + "函数返回结果:" + strlist[1] + "\r\n"
dispstr = dispstr + "卡片返回代码:" + strlist[2] + "\r\n"
if (strlist[2] == "91AE") {
dispstr = dispstr + "返回代码说明:更改密码指令被禁止或密码未认证或密码不对,请先用0号密码认证后再试!\r\n"
} else {
dispstr = dispstr + "返回代码说明:" + strlist[3] + "\r\n"
}
returninfo.value = dispstr;
break;
case "ntagsetconfiguration":
dispstr = "执行函数名称:" + strlist[0] + " 更改标签配置操作\r\n";
dispstr = dispstr + "函数返回结果:" + strlist[1] + "\r\n"
dispstr = dispstr + "卡片返回代码:" + strlist[2] + "\r\n"
if (strlist[2] == "91AE") {
dispstr = dispstr + "返回代码说明:更改为随机UID指令被禁止或密码未认证或密码不对,请先用正确的密码号进行认证再试!\r\n"
} else {
dispstr = dispstr + "返回代码说明:" + strlist[3] + "\r\n"
}
returninfo.value = dispstr;
break;
case "forumtype4_write_ndeftag":
dispstr = "函数名称:" + strlist[0] + "\r\n";
if (strlist[1] == "ReturnCode:000") {
dispstr = dispstr + "操作结果:" + strlist[1] + ",写入标签成功!\r\n";
dispstr = dispstr + "标签号码:" + strlist[2];
} else {
dispstr = dispstr + "操作结果:" + strlist[1] + DispErrInfo(strlist[1]);
}
returninfo.value = dispstr;
break;
case "forumtype4getuid":
dispstr = "函数名称:" + strlist[0] + "\r\n";
if (strlist[1] == "ReturnCode:000") {
dispstr = dispstr + "操作结果:" + strlist[1] + ",读取标签真实UID成功!\r\n";
dispstr = dispstr + "标签号码:" + strlist[2];
} else {
dispstr = dispstr + "操作结果:" + strlist[1] + DispErrInfo(strlist[1]);
}
returninfo.value = dispstr;
break;
case "forumtype4_read_ndeftag":
dispstr = "函数名称:" + strlist[0] + "\r\n";
if (strlist[1] == "ReturnCode:000") {
dispstr = dispstr + "操作结果:" + strlist[1] + ",读取标签NDEF记录成功!\r\n";
dispstr = dispstr + "标签号码:" + strlist[2] + "\r\n";
dispstr = dispstr + strlist[3] ;
} else {
dispstr = dispstr + "操作结果:" + strlist[1] + DispErrInfo(strlist[1]);
}
returninfo.value = dispstr;
break;
case "ntagreadfilesettings":
dispstr = "函数名称:" + strlist[0] + "\r\n";
if (strlist[1] == "ReturnCode:000") {
dispstr = dispstr + "操作结果:" + strlist[1] + ",读取标签配置信息!\r\n";
dispstr = dispstr + "返回代码:" + strlist[2] + "\r\n";
dispstr = dispstr + "配置信息:" + strlist[3] + "\r\n";
text_setup.value = strlist[3];
} else {
dispstr = dispstr + "操作结果:" + strlist[1] + DispErrInfo(strlist[1]);
}
returninfo.value = dispstr;
break;
case "ntagchangefilesettings":
dispstr = "执行函数名称:" + strlist[0] + " 更改标签配置操作\r\n";
dispstr = dispstr + "函数返回结果:" + strlist[1] + "\r\n";
dispstr = dispstr + "卡片返回代码:" + strlist[2] + "\r\n";
if (strlist[2] == "91AE") {
if (select_RWsetconnmodel.selectedIndex == 1) {
dispstr = dispstr + "返回代码说明:更改指令被禁止或密码未认证或密码不对,请先用正确的密码号进行认证再试!\r\n";
} else {
dispstr = dispstr + "返回代码说明:更改指令被禁止或不支持明文操作,请先用正确的密码号进行认证并且选择"密文+MAC保护的通信模式"再试!\r\n";
}
} else {
dispstr = dispstr + "返回代码说明:" + strlist[3] + "\r\n";
}
returninfo.value = dispstr;
break;
}
}
ButtonEnabled(); //恢复按键的onclick事件
}
function WebSocketRun(sendinfo) { //websockket发送指令
iswsrun = false;
try {
if ("WebSocket" in window) {
ws = new WebSocket(wsUri);
}
else if ("MozWebSocket" in window) {
ws = new MozWebSocket(wsUri);
}
else {
ButtonEnabled(); //恢复按键的onclick事件
received_msg = "您的浏览器不支持WebSocket,请选用支持WebSocket的浏览器!";
return;
}
clearTimeout(mytimer);
ws.onopen = function (evt) {
ws.send(sendinfo);
iswsrun = true;
if (sendinfo == 'NDEF_Clear,' || sendinfo == 'NDEF_BuffWriteTag,') {
mytimer = setTimeout("timeoutevent()", 5000); //清除标签的时间要长
} else { mytimer = setTimeout("timeoutevent()", 2000); }
};
ws.onmessage = WebSocketRev;
ws.onerror = function (e) {
if (iswsrun != true) {
received_msg = "请先在当前电脑下载>安装>运行我们的服务程序......";
window.open("http://www.bossknow.cn:90/RongShiWebReaderTest/RFIDWebPluginSetup_Windows.rar", "top");//打开新窗口
ButtonEnabled(); //恢复按键的onclick事件
alert("请先下载>安装>运行我们的服务程序,再刷新本页面......");
}
};
}
catch (ex) {
if (iswsrun != true) {
received_msg = "请先在当前电脑下载>安装>运行我们的服务程序......";
window.open("http://www.bossknow.cn:90/RongShiWebReaderTest/RFIDWebPluginSetup_Windows.rar", "top");//打开新窗口
ButtonEnabled(); //恢复按键的onclick事件
alert("请先下载>安装>运行我们的服务程序,再刷新本页面......");
}
}
}
</script>
<style>
*{box-sizing:border-box;font-family:"Microsoft Yahei",SimSun,system-ui;font-size:13px;}
body{background:#ececec;margin:8px;}
.win-container{
background:#f0f0f0;
border:1px solid #999;
padding:10px;
max-width:1400px;
}
button{
padding:6px 12px;
border:1px solid #666;
background:#f8f8f8;
border-radius:3px;
cursor:pointer;
}
button.green{background:#39d060;color:#000;font-weight:bold;}
button.cyan{background:#72e0f5;}
input[type=text]{
padding:4px;
border:1px solid #999;
background:#fff;
}
select{padding:3px;border:1px solid #999;}
.warn-yellow{
background:#fff260;
color:#000;
padding:4px 6px;
margin:6px 0;
font-weight:bold;
}
.row{display:flex;gap:8px;align-items:center;margin:6px 0;flex-wrap:wrap;}
.col-block{border:1px solid #aaa;padding:8px;margin:6px 0;background:#f7f7f7;}
.red-text{color:#c00000;font-weight:bold;}
</style>
</head>
<body>
<div align="center">
<div class="win-container">
<h3 style="margin:0 0 8px 0;">Ntag 424 DNA标签读写</h3>
<div class="row">
<button style="width:200px" id="butt_beep" onclick="beepDevice()">让设备发出声响</button>
<button id="butt_getdevnum" onclick="getdevicenumber()">读出设备全球唯一的设备编号,作为加密狗用</button>
<div style="margin-left:auto;">
<button id="butt_getcardtype" onclick="geticcardtype()">获取IC卡芯片型号</button>
</div>
</div>
<div class="row">
<button style="width:200px" id="butt_cpurequest1" onclick="cpu_cpurequest1()">第一步:激活 Ntag 424</button>
<span>16进制卡号:</span>
<input type="text" id="carduid" style="width:200px;">
<span class="warn-yellow red-text">注:每次拿开卡重放后都需要激活,才能驱动卡进入14443‑4协议状态。</span>
</div>
<div class="row">
<button style="width:200px" id="butt_selectappid" onclick="selectappid()">第二步:选择卡内已有的应用</button>
<span>选择卡内应用:</span>
<select id="seleappid" onchange="changeapp()">
<option selected="selected">424卡的ISO MF Name</option>
<option>424卡的ISO File ID(3F00)</option>
<option>424卡的ISO DF Name</option>
<option>424卡的ISO File ID(E110)</option>
</select>
<select id="selefileid">
<option>ISO DF/MF Name</option>
<option>ISO FileID</option>
</select>
<select id="selefci">
<option>Return FCI</option>
<option>no FCI</option>
</select>
<span>16进制目标:</span>
<input type="text" id="objedata" value="D2 76 00 00 85 01 00" style="width:350px;" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F ]/g,'')">
</div>
<div class="row">
<button style="width:200px" id="butt_desfireauthkeyev2" onclick="desfireauthkeyev2()">密钥认证</button>
<span>认证密钥:</span>
<select id="selectauthkey">
<option selected="selected">0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
<span>16进制旧认证密钥:</span>
<input type="text" id="text_authkey" value="00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" style="width:420px;" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F ]/g,'')">
<span>加解密方法:</span>
<select id="selectdecnec">
<option selected="selected">EV2First(命令71h)</option>
<option>EV2NonFirst(命令77h)</option>
</select>
</div>
<div class="row">
<button style="width:200px" id="butt_ntagchangkey" onclick="ntagchangkey()">更改密钥</button>
<span>更改密钥:</span>
<select id="selectnewkey">
<option>0</option>
<option selected>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
<span style="margin-left:27px;">16进制新密钥:</span>
<input type="text" id="text_newkey" value="00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" style="width:420px;" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F ]/g,'')">
</div>
<div class="row">
<button id="butt_ntagsetconfiguration" onclick="ntagsetconfiguration()">将424卡配置成随机 UID 模式</button>
<span class="warn-yellow red-text">注:424卡更改为随机UID模式后,此卡将永久为随机模式!!!</span>
</div>
<div class="col-block">
<strong>Ntag 424 DNA卡写入NDEF URI记录</strong>
<div class="row">
<button id="butt_examples1" onclick="examples1()">例子1:动态UID(可解析出真正的UID)</button>
<button id="butt_examples2" onclick="examples2()">例子2:直接UID和计数器</button>
<button id="butt_examples3" onclick="examples3()">例子3:动态UID+加密数据+MAC</button>
<div style="margin-left:auto;">
<span>光标处的偏移量:</span>
<input type="text" id="text_selestar" style="width:100px;">
</div>
</div>
<div class="row">
<span>标题名称:</span>
<input type="text" id="text_title" value="百度" style="width:100px;">
<span>前缀:</span>
<select id="select_prefix">
<option>无前缀</option>
<option>http://www.</option>
<option selected>https://www.</option>
<option>http://</option>
<option>https://</option>
<option>tel:</option>
<option>mailto:</option>
<option>ftp://anonymous:anonymous@</option>
<option>ftp://ftp.</option>
<option>ftps://</option>
<option>sftp://</option>
<option>smb://</option>
<option>nfs://</option>
<option>ftp://</option>
<option>dav://</option>
<option>news:</option>
<option>telnet://</option>
<option>imap:</option>
<option>rtsp://</option>
<option>urn:</option>
<option>pop:</option>
<option>sip:</option>
<option>sips:</option>
<option>tftp:</option>
<option>btspp://</option>
<option>btl2cap://</option>
<option>btgoep://</option>
<option>tcpobex://</option>
<option>irdaobex://</option>
<option>file://</option>
<option>urn:epc:id:</option>
<option>urn:epc:tag:</option>
<option>urn:epc:pat:</option>
<option>urn:epc:raw:</option>
<option>urn:epc:</option>
<option>urn:nfc:</option>
</select>
<input type="text" id="text_uri" value="baidu.com" style="flex:1;box-sizing:border-box;" onclick="getCaretPos()">
</div>
<div class="row">
<label><input type="checkbox" id="check_RWAuthKey"> 读写卡片需要认证密码,密码号:</label>
<select id="select_RWAuthKeyId">
<option>0</option>
<option>1</option>
<option>2</option>
<option selected>3</option>
<option>4</option>
</select>
<span>16进制认证密钥:</span>
<input style="width:380px;" type="text" id="text_RWauthkey" value="00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F ]/g,'')">
<span>通信模式:</span>
<select id="select_RWCommMode">
<option selected>明文</option>
<option>MAC保护</option>
<option>密文+MAC保护</option>
</select>
<button class="cyan" id="butt_forumtype4_write_ndeftag_uri" onclick="forumtype4_write_ndeftag_uri()">将URI网址写入424DNA卡</button>
</div>
<div class="row">
<label><input type="checkbox" id="check_AnalyzeImage"> 解析镜像,SDM元 数据读取密钥:</label>
<input type="text" id="text_SDMkey" value="00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" style="width:365px;" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F ]/g,'')">
<span>CMAC验证密钥:</span>
<input type="text" id="text_CMACkey" value="00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" style="width:365px;" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F ]/g,'')">
<button id="butt_forumtype4getuid" onclick="forumtype4getuid()">读取卡片真实UID</button>
<button class="green" id="butt_forumtype4_read_ndeftag" onclick="forumtype4_read_ndeftag()">读取卡内NDEF记录</button>
</div>
</div>
<div class="warn-yellow">更改或读取文件配置(2号文件,为Standard Data File或 NDEF File,默认通信模式为明文)</div>
<div class="col-block">
<div class="row">
<span>通讯模式:</span>
<select id="select_SetCommMode">
<option selected>明文</option>
<option>MAC保护</option>
<option>密文+MAC保护</option>
</select>
<span class="red-text">首选明文通讯,尽量不要更改这里!!!</span>
</div>
<div class="row">
<span style="margin-left:100px;">只读指令需要先认证的密码:</span>
<select id="select_readonlykey">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option selected>无需密码</option>
<option>禁止操作</option>
</select>
<span style="margin-left:50px;">只写指令需要先认证的密码:</span>
<select id="select_writeonlykey">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option selected>无需密码</option>
<option>禁止操作</option>
</select>
<span style="margin-left:50px;">读写指令需要先认证的密码:</span>
<select id="select_readwritekey">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option selected>无需密码</option>
<option>禁止操作</option>
</select>
<div style="margin-left:50px;">
<span>更改指令需要先认证的密码:</span>
<select id="select_changesetkey">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option selected>无需密码</option>
</select>
</div>
</div>
<div align="right" >
<div class="red-text">
注意:更改指令需要先认证的密码如设为禁止操作,以后将不能用5F指令更改配置,如设为无需密码,下次更改配置需要用明文的通讯模式!
</div>
</div>
<div align="left">
<label><input type="checkbox" id="check_SDMMirrorImageEn"> 启用SDM镜像</label>
<div class="row">
<label style="margin-left:50px;"><input type="checkbox" id="check_UIDMirrorImageEn"> 启用UID镜像</label>
<span>SDM元数据读取访问权限:</span>
<select id="select_SDMRead">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option selected>无需密码</option>
<option>禁止操作</option>
</select>
<span style="margin-left:90px;">UID镜像位置:</span>
<input type="text" value="0" style="width:70px;" id="text_UIDMirrorImage">
<span style="margin-left:50px;">PICCDataOffset:</span>
<input type="text" value="0" style="width:70px;" id="text_PICCDataOffset">
</div>
<div class="row">
<span style="margin-left:150px;">面向CMAC计算的派生密钥:</span>
<select id="select_CMACCalc">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option selected>禁止操作</option>
</select>
<span style="margin-left:45px;">SDMMACInputOffset:</span>
<input type="text" value="0" style="width:70px;" id="text_SDMMACInputOffset">
<span style="margin-left:50px;">SDMMACoffset:</span>
<input type="text" value="0" style="width:70px;" id="text_SDMMACoffset">
</div>
<div class="row">
<label style="margin-left:50px;"><input type="checkbox" id="check_CounMirrorImageEn"> 启用计数器镜像</label>
<span style="margin-left:10px;">SDM计数器检索密钥:</span>
<select id ="select_SDMCount">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>无需密码</option>
<option selected>禁止操作</option>
</select>
<span style="margin-left:75px;">计数器数据位置:</span>
<input type="text" value="0" style="width:70px;" id="text__Counoffset">
</div>
<div class="row">
<label style="margin-left:50px;"><input type="checkbox" id="check_CounLimitEn"> 启用计数器限额</label>
<span style="margin-left:55px;">计数器限额值:</span>
<input type="text" value="0" style="width:80px;" id="text_CounLimit">
<span class="red-text">当计数器的值达到计数器限额值时,或计数器的值达到16777215时,读ndef文件时将返回错误!</span>
</div>
<div class="row">
<label style="margin-left:50px;"><input type="checkbox" id="check_SDMENCFileData"> SDMENCFileData</label>
<span style="margin-left:34px;">SDMENCOffset:</span>
<input type="text" value="0" style="width:80px;" id="text_SDMENCOffset">
<span style="margin-left:75px;">SDMENCLength:</span>
<input type="text" value="0" style="width:70px;" id="text_SDMENCLength">
</div>
<div class="row">
<button style="display:none" id="butt_getcountervalue" onclick="getcountervalue()">读取卡片计数器值</button>
<button id="butt_ntagreadfilesettings" onclick="ntagreadfilesettings()">读取卡片配置信息</button>
<span>本次操作的通信模式:</span>
<select id="select_RWsetconnmodel">
<option>明文</option>
<option>密文+MAC保护</option>
</select>
<span>卡配置信息:</span>
<input type="text" style="width:500px;" id="text_setup" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F ]/g,'')">
<div style="margin-left:auto;">
<button class="cyan" id="butt_ntagchangefilesettings" onclick="ntagchangefilesettings()">更改卡片配置信息</button>
</div>
</div>
</div>
<div>
<textarea style="color:blue;width:100%" name="returninfo" id="returninfo" cols="140" rows="13"></textarea>
</div>
</div>
</div>
</div>
<p align="center">以上功能需要插件支持,在发送读卡、写卡操作请求之前,请先确保您的电脑已安装并运行我们的读写器插件: <a href="http://www.bossknow.cn:90/RongShiWebReaderTest/RFIDWebPluginSetup_Windows.rar"> RFIDWebPlugin</a> </p>
<p align="center"><a href="http://www.bossknow.cn:90/RongShiWebReaderTest/RFIDWebPluginSetup.html">如何防止RFIDWebPlugin插件被杀毒软件误报删除</a></p>
</body>
</html>