MIFARE 卡 1k 是否可以锁定命令,保护克隆或不可被其他应用程序擦除
Is it possible to lock command, protect cloning or not erasable by other app for MIFARE card 1k
我想这样做是为了防止卡被擦除或克隆。我看了很多文件
有的告诉用户第四块设置读写权限..
根据@Michael Roland
MIFARE 卡每个扇区的验证密钥和访问条件位于该扇区的最后一个块(扇区尾部)。您可以使用常规写入命令使用新的访问条件和身份验证密钥更新此块。
扇区预告片如下所示:
+-----------------------------+--------------+----+-----------------------------+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
+-----------------------------+--------------+----+-----------------------------+
| Key A | Access Bits | GP | Key B |
| (6 bytes) | (3 bytes) | B | (6 bytes) |
+-----------------------------+--------------+----+-----------------------------+
因此访问位位于字节 6-8 中,如下所示:
+-------+-------+-------+-------+-------+-------+-------+-------+
| Bit 0 | Bit 1 | Bit 2 | Bit 3 | Bit 4 | Bit 5 | Bit 6 | Bit 7 |
+-------+-------+-------+-------+-------+-------+-------+-------+
Byte 6: | nC2_3 | nC2_2 | nC2_1 | nC2_0 | nC1_3 | nC1_2 | nC1_1 | nC1_0 |
+-------+-------+-------+-------+-------+-------+-------+-------+
Byte 7: | C1_3 | C1_2 | C1_1 | C1_0 | nC3_3 | nC3_2 | nC3_1 | nC3_0 |
+-------+-------+-------+-------+-------+-------+-------+-------+
Byte 8: | C3_3 | C3_2 | C3_1 | C3_0 | C2_3 | C2_2 | C2_1 | C2_0 |
+-------+-------+-------+-------+-------+-------+-------+-------+
Where nCx_y = not Cx_y and "C1_x, C2_x, C3_x" is the access condition for block x:
C1_3, C2_3, C3_3: sector trailer (block 3 in this sector)
C1_2, C2_2, C3_2: block 2 in this sector
C1_1, C2_1, C3_1: block 1 in this sector
C1_0, C2_0, C3_0: block 0 in this sector
我如何在正在进行的项目中执行此操作
您可以使用密钥 A 或密钥 B 保护每个扇区。
也就是说,此时 Mifare Classic 卡的安全性已被破坏。你真的无法保护任何东西。
你不能保护一张卡在她自己身上复制。 (force brut方法很容易应用在这个技术上)
可以做的是所有块的散列,包括存储在 card.In 程序中的 UID,您只需将数据散列与存储的散列进行比较。
要在 python 中实现非常基本的哈希并将其存储在一个块中,您可以使用双伪随机数:
def CRYPT_hashage(data,UID):
seed(str(data)+str(UID))
seed(random())
return str(random()).replace("0.","")[:8]
它防止在另一张卡上克隆。用户仍然可以修改自己的卡。但是您可以使用相同的技术对 'sensitives' 数据进行哈希处理。
这2个证券之后,就只剩下"cloning on herself"技术了,例如:
- 你复制你的数据
- 你付钱(无现金支付系统)
- 您将旧数据粘贴到您的卡上)
防止它的唯一方法是仅使用卡的 UID 作为主键将所有数据存储在服务器上。
存在可以更改UID的卡。
最后,我解决了这个解决方案
为此,我们需要更改第四块每个扇区的访问位
以扇区 5 为例
就像扇区 5 一样,我们需要更改它的 23 个块上的访问位
我们需要先验证扇区 5...
默认键是
byte keya[] = { (byte) 0xFF,(byte) 0xFF,(byte) 0xFF,(byte) 0xFF,(byte) 0xFF,(byte) 0xFF};
这是 000000000000FF078069FFFFFFFFFFFF
第一位 6 用于密钥 A,即 000000000000,最后 6 位用于密钥 B,即 FFFFFFFFFFFF 十六进制字符串
FF078069 十六进制字符串是访问位
所以为了改变这一点,我们第一次需要像这样实现我们需要使用默认密钥进行身份验证
MifareClassic mfc = MifareClassic.get(tag);
try {
mfc.connect();
auth = mfc.authenticateSectorWithKeyA(5,
MifareClassic.KEY_DEFAULT);
if(auth)
{
String nkeya = "key123";// 6 length only
nkeya = toHex(nkeya).toUpperCase();
nkeya = nkeya.substring(28,40);
String nkeyb = "key123"; // 6 length only
nkeyb = toHex(nkeyb).toUpperCase();
nkeyb = nkeyb.substring(28,40);
String nkey = nkeya+"FF078069"+nkeyb;
int len = nkey.length();
byte[] nkeyab = new BigInteger(nkey, 16).toByteArray();
// 5 is sector and 5*4+3 is fourth block of sector 5
mfc.writeBlock((5*4)+3,nkeyab);
}
catch(Execption e)
{
}
写保护成功后默认认证失败
所以我们需要使用我们创建的访问密钥进行身份验证
try {
MifareClassic mfc = MifareClassic.get(tag);
String key = getKeya();
key = toHex(key).toUpperCase();
int len = key.length();
key = key.substring(28,40);
keya = new BigInteger(key, 16).toByteArray();
//for key A or for Keb b
mfc.connect();
auth = mfc.authenticateSectorWithKeyA(5, keya);
if(auth)
{
byte[] readblock4= mfc.readBlock(20);
}
}
catch(Exeption e)
{
}
我想这样做是为了防止卡被擦除或克隆。我看了很多文件 有的告诉用户第四块设置读写权限..
根据@Michael Roland
MIFARE 卡每个扇区的验证密钥和访问条件位于该扇区的最后一个块(扇区尾部)。您可以使用常规写入命令使用新的访问条件和身份验证密钥更新此块。
扇区预告片如下所示:
+-----------------------------+--------------+----+-----------------------------+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
+-----------------------------+--------------+----+-----------------------------+
| Key A | Access Bits | GP | Key B |
| (6 bytes) | (3 bytes) | B | (6 bytes) |
+-----------------------------+--------------+----+-----------------------------+
因此访问位位于字节 6-8 中,如下所示:
+-------+-------+-------+-------+-------+-------+-------+-------+
| Bit 0 | Bit 1 | Bit 2 | Bit 3 | Bit 4 | Bit 5 | Bit 6 | Bit 7 |
+-------+-------+-------+-------+-------+-------+-------+-------+
Byte 6: | nC2_3 | nC2_2 | nC2_1 | nC2_0 | nC1_3 | nC1_2 | nC1_1 | nC1_0 |
+-------+-------+-------+-------+-------+-------+-------+-------+
Byte 7: | C1_3 | C1_2 | C1_1 | C1_0 | nC3_3 | nC3_2 | nC3_1 | nC3_0 |
+-------+-------+-------+-------+-------+-------+-------+-------+
Byte 8: | C3_3 | C3_2 | C3_1 | C3_0 | C2_3 | C2_2 | C2_1 | C2_0 |
+-------+-------+-------+-------+-------+-------+-------+-------+
Where nCx_y = not Cx_y and "C1_x, C2_x, C3_x" is the access condition for block x:
C1_3, C2_3, C3_3: sector trailer (block 3 in this sector)
C1_2, C2_2, C3_2: block 2 in this sector
C1_1, C2_1, C3_1: block 1 in this sector
C1_0, C2_0, C3_0: block 0 in this sector
我如何在正在进行的项目中执行此操作
您可以使用密钥 A 或密钥 B 保护每个扇区。
也就是说,此时 Mifare Classic 卡的安全性已被破坏。你真的无法保护任何东西。
你不能保护一张卡在她自己身上复制。 (force brut方法很容易应用在这个技术上)
可以做的是所有块的散列,包括存储在 card.In 程序中的 UID,您只需将数据散列与存储的散列进行比较。
要在 python 中实现非常基本的哈希并将其存储在一个块中,您可以使用双伪随机数:
def CRYPT_hashage(data,UID):
seed(str(data)+str(UID))
seed(random())
return str(random()).replace("0.","")[:8]
它防止在另一张卡上克隆。用户仍然可以修改自己的卡。但是您可以使用相同的技术对 'sensitives' 数据进行哈希处理。
这2个证券之后,就只剩下"cloning on herself"技术了,例如: - 你复制你的数据 - 你付钱(无现金支付系统) - 您将旧数据粘贴到您的卡上)
防止它的唯一方法是仅使用卡的 UID 作为主键将所有数据存储在服务器上。
存在可以更改UID的卡。
最后,我解决了这个解决方案
为此,我们需要更改第四块每个扇区的访问位
以扇区 5 为例
就像扇区 5 一样,我们需要更改它的 23 个块上的访问位
我们需要先验证扇区 5...
默认键是
byte keya[] = { (byte) 0xFF,(byte) 0xFF,(byte) 0xFF,(byte) 0xFF,(byte) 0xFF,(byte) 0xFF};
这是 000000000000FF078069FFFFFFFFFFFF
第一位 6 用于密钥 A,即 000000000000,最后 6 位用于密钥 B,即 FFFFFFFFFFFF 十六进制字符串
FF078069 十六进制字符串是访问位
所以为了改变这一点,我们第一次需要像这样实现我们需要使用默认密钥进行身份验证
MifareClassic mfc = MifareClassic.get(tag);
try {
mfc.connect();
auth = mfc.authenticateSectorWithKeyA(5,
MifareClassic.KEY_DEFAULT);
if(auth)
{
String nkeya = "key123";// 6 length only
nkeya = toHex(nkeya).toUpperCase();
nkeya = nkeya.substring(28,40);
String nkeyb = "key123"; // 6 length only
nkeyb = toHex(nkeyb).toUpperCase();
nkeyb = nkeyb.substring(28,40);
String nkey = nkeya+"FF078069"+nkeyb;
int len = nkey.length();
byte[] nkeyab = new BigInteger(nkey, 16).toByteArray();
// 5 is sector and 5*4+3 is fourth block of sector 5
mfc.writeBlock((5*4)+3,nkeyab);
}
catch(Execption e)
{
}
写保护成功后默认认证失败 所以我们需要使用我们创建的访问密钥进行身份验证
try {
MifareClassic mfc = MifareClassic.get(tag);
String key = getKeya();
key = toHex(key).toUpperCase();
int len = key.length();
key = key.substring(28,40);
keya = new BigInteger(key, 16).toByteArray();
//for key A or for Keb b
mfc.connect();
auth = mfc.authenticateSectorWithKeyA(5, keya);
if(auth)
{
byte[] readblock4= mfc.readBlock(20);
}
}
catch(Exeption e)
{
}