- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试使用我的 Android 应用程序验证 DESFire 卡。我用 the example in this link解密我从卡上得到的字节。为此,我排除了解密中的填充(在下面注释掉),因为 DESFire 文档指出了这一点。另外,如果我不这样做,解密会为 8 个字节的输入返回 7 个字节。下面是我使用的DES和TripleDES解密函数:
public static byte[] TripleDES_Decrypt(byte[] data,byte[][] keys)
{
int i;
byte[] tmp = new byte[data.length];
byte[] bloc = new byte[8];
K = generateSubKeys(keys[0]);
K1 = generateSubKeys(keys[1]);
K2 = generateSubKeys(keys[2]);
for (i = 0; i < data.length; i++) {
if (i > 0 && i % 8 == 0) {
bloc = encrypt64Bloc(bloc,K2, true);
bloc = encrypt64Bloc(bloc,K1, false);
bloc = encrypt64Bloc(bloc,K, true);
System.arraycopy(bloc, 0, tmp, i - 8, bloc.length);
}
if (i < data.length)
bloc[i % 8] = data[i];
}
bloc = encrypt64Bloc(bloc,K2, true);
bloc = encrypt64Bloc(bloc,K1, false);
bloc = encrypt64Bloc(bloc,K, true);
System.arraycopy(bloc, 0, tmp, i - 8, bloc.length);
//tmp = deletePadding(tmp);
return tmp;
}
public static byte[] decrypt(byte[] data, byte[] key) {
int i;
byte[] tmp = new byte[data.length];
byte[] bloc = new byte[8];
K = generateSubKeys(key);
for (i = 0; i < data.length; i++) {
if (i > 0 && i % 8 == 0) {
bloc = encrypt64Bloc(bloc,K, true);
System.arraycopy(bloc, 0, tmp, i - 8, bloc.length);
}
if (i < data.length)
bloc[i % 8] = data[i];
}
bloc = encrypt64Bloc(bloc,K, true);
System.arraycopy(bloc, 0, tmp, i - 8, bloc.length);
//tmp = deletePadding(tmp);
return tmp;
}
根据DesFire文档,我需要两种解密方式,发送和接收。 This blog post对此有一些解释。
However, the DESFire crypto is a bit different from the normal DES/CBC scheme: The PCD uses DES “send mode” when sending data (xor before DES), and the card uses DES “recieve mode” when recieving data (xor after DES). But when the PCD recieves data, it uses normal DES/CBC mode (xor after DES), and the card uses normal DES send mode when sending data (xor before DES).
在 Android 方面,我遵循示例和建议:
// connected to tag and application
// result = encoded(randB) + af
byte[] result = idTag.transceive(Utils.wrapMessage((byte)0x0a, new byte[]{(byte)0x0}));
byte[] b0 = new byte[8];
for(int i = 0; i < 8; i++) {
b0[i] = result[i];
}
// key
byte[] key = new byte[] {(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0 };
byte[][] keys = new byte[3][];
keys[0]=key; keys[1]=key; keys[2]=key;
// decrypt encoded(randB)
byte[] r0 = DES.TripleDES_Decrypt(b0, keys);
// generate randA (integer 0-7 for trying)
byte[] nr = new byte[8];
for(int i = 0; i < 8; i++) {
nr[i] = Byte.parseByte(Integer.toString(i), 16);
}
// decrypt randA
byte[] b1 = DES.TripleDES_Decrypt(nr, keys);
// shift randB and get randB'
byte[] r1 =new byte[8];
for(int i = 0; i < 7; i++) {
r1[i] = r0[i + 1];
}
r1[7]=r0[0];
// concat (randA + randB')
byte[] b2 = new byte[16];
for(int i = 0; i < 16; i++)
{
if(i <= 7) {
b2[i] = b1[i];
} else {
b2[i] = r1[i - 8];
}
}
// XOR (randA + randB') with IV
// IV is told to be consisting of 0's,
// but XOR something with 0 results the same?
for(int i=0;i<16;i++) {
b2[i] = (byte) (b2[i] ^ (byte)0x0);
}
// send AF and decrypt(A+B)
// wrap message adds needed wrapping to message (90 to left, offset bytes etc.)
result = isodepTag.transceive(Utils.wrapMessage((byte)0xaf, DES.TripleDES_Decrypt(b2, keys)));
我得到了第一个结果,即加密的 randB。但是,第二个“结果”始终是“91ae”,表示身份验证错误。我在这里做错了,向卡发送了错误的数据。
谁能告诉我必须在代码中更改哪些内容才能在这些模式下工作?我应该对 TripleDES 之前/之后的数据进行什么异或?
不是真正的问题,但我读到 DesFire 卡中的默认“ key ”是 16 个零字节。文档还指出我需要对 16 个字节的 key 使用 TripleDES,对 8 个字节的 key 使用 DES。所以我正在使用并且需要使用 TripleDES,因为我没有更改默认 key ,对吗?
对于那些需要了解 CipherBlockChaining 的人.
编辑:我发现我需要在 TripleDES 之前和之后进行 XORing,而且我根本不能触及 TripleDES 的内部操作。我会在一段时间内尝试。
删除了里面的 TripleDES 行,仅供第一次看到该问题的人使用。
最佳答案
好的,我找到了解决方案。我的错误是我发送了
3DES(randA + randB')
但我应该发送
3DES(randA) + 3DES(randB' XOR 3DES(randA))
这是Android/Java的验证码(可惜目前网上只有这个!):
实际验证码:
// send initial authentication request
byte[] result = idTag.transceive(Utils.wrapMessage((byte)0x0a, new byte[]{(byte)0x0}));
// get encrypted(randB) from the response
byte[] b0 = new byte[8];
for(int i = 0; i < 8; i++) {
b0[i] = result[i];
}
// 16 bytes default key
byte[] key = new byte[] {(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0 };
// keys for TripleDes
byte[][] keys = new byte[3][];
keys[0] = key; keys[1] = key; keys[2] = key;
// decrypt encoded(randB)
byte[] r0 = DES.TripleDES_Decrypt(b0, keys);
// generate randA (integer 0-7 for trying, should randomize for real-life use)
byte[] nr = new byte[8];
for(int i = 0; i < 8; i++) {
nr[i] = Byte.parseByte(Integer.toString(i), 16);
}
// decrypt randA, should XOR with IV, but IV is all 0's, not necessary
byte[] b1 = DES.TripleDES_Decrypt(nr, keys);
// shift randB one byte left and get randB'
byte[] r1 =new byte[8];
for(int i = 0; i < 7; i++) {
r1[i] = r0[i + 1];
}
r1[7]=r0[0];
// xor randB' with randA and decrypt
byte[] b2 = new byte[8];
for(int i = 0; i < 8; i++) {
b2[i] = (byte) (b1[i] ^ r1[i]);
}
b2 = DES.TripleDES_Decrypt(b2, keys);
// concat (randA + randB')
byte[] b1b2 = new byte[16];
for (int i = 0; i < b1b2.length; i++) {
if(i <= 7) {
b1b2[i] = b1[i];
} else {
b1b2[i]=b2[i-8];
}
}
result = idTag.transceive(Utils.wrapMessage((byte)0xaf, b1b2));
TripleDes 是问题中的那个。 wrapMessage 函数:
public static byte[] wrapMessage (byte command, byte[] parameters) throws Exception {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
stream.write((byte) 0x90);
stream.write(command);
stream.write((byte) 0x00);
stream.write((byte) 0x00);
if (parameters != null) {
stream.write((byte) parameters.length);
stream.write(parameters);
}
stream.write((byte) 0x00);
return stream.toByteArray();
}
编辑:感谢 VGe0rge,我们发现了此身份验证有时不起作用的原因。不要在问题中调用 3DES 函数,只需调用:
Cipher.getInstance("DESede/CBC/NoPadding");
关于java - DESFire 身份验证的 DES 发送和接收模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14117025/
我有一张非接触式卡,并且我知道它是 MIFARE 卡。我没有文件,也没有身份验证 key 。重置后,我收到以下 ATS: myubuntu@lol-MS-7693:~$ nfc-list nfc-li
在多个 Android 设备上,Mifare DESFire 通信被路由到 HCE 而不是脱离主机 (UICC)。 通过基于 OMAPI 与脱离主机安全元素的通信,我已经学会了如何将 AID 添加到
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
Stackoverflow 上有很多关于 Desfire EV1 卡的问题。 但是如果你搜索一些示例数据,你会发现几个字节的唯一地方是 Ridrix Blog .但这很不完整。 很多人在为 Desfi
有没有办法将 DESFire 卡重置为原始状态?是否有格式化和删除所有内容的命令? 我读到 DeleteApplication apdu 命令删除了应用程序及其文件,但空间仍然不可用。 谢谢。 最佳答
我需要在 Android 设备上模拟 DESFire EV1 卡。但是,我对如何将 Mifare SDK(精简版或高级版)与 HCE 结合使用感到困惑。 这可能吗?我需要开始这个项目,我对数据如何在
我知道如何从 Mifare DESFire 标签读取和写入 ndef 消息,但在与 Android 进行通信时,我很难理解如何使用 DESFire 支持的命令集。 我知道它与 transceive(b
上周我一直在尝试使用具有默认 key (00000000h) 的 MIFARE DESFire EV1 卡进行身份验证,但无济于事。我关注了this blog对信的指示。我实现了Send mode C
我已经实现了 AES key 多样化 AV2,现在我想知道什么是 SAM AV1,它是如何工作的?任何人都可以分享链接或提供一些信息吗? 只是为了分享一些知识,以 AV2 为例: /*
当使用 Desfire 原生包装的 APDU 与卡通信时,必须使用命令和响应的哪些部分来计算 CMAC? 身份验证成功后,我有以下 session key : Session Key: 7CCEBF7
我现在有一张新的 Desfire EV1 卡。我想用 AES 加密设置 PICC 主 key 。我怎么能那样做?到目前为止,我可以使用单个 DES 获取 session key 。 最佳答案 您需要从
我有一个使用 MIFARE DESFIRE EV1 卡创建考勤系统的项目。 我需要用于此项目的读卡器品牌仅支持 ISO 7816-x,因此我需要使用 DESFIRE ISO7816-4 APDU Wr
我正在尝试使用我的 Android 应用程序验证 DESFire 卡。我用 the example in this link解密我从卡上得到的字节。为此,我排除了解密中的填充(在下面注释掉),因为 D
我在使用 MIFARE DESFire 时遇到了一个非常奇怪的问题。当我写入少量数据(例如11字节)时,写入操作成功。然而,当我尝试写例如50字节,响应为917E,说明命令存在长度问题。 尝试写入11
有没有人知道如何解密从卡发送的第一条消息?我的意思是在身份验证成功之后,然后你发送一个命令(例如 0x51 (GetRealTagUID)。它返回 00+random32bits(总是不同的)。我尝试
哪种类型的 CRC 用于更改 Desfire 卡中的 key ?CRC 字节的顺序是否应该颠倒。我无法更改 PICC 应用程序的 key 。任何人都可以帮忙吗? 最佳答案 CRC16/32 和 MAC
我正在尝试使用以下几行将一些数据写入带有 Galaxy S3 的 Mifare DesFire 卡: private byte[] wrapMessage (byte command, byte[]
从 DESFire EVO1 卡(AES 加密)读取数据时,出现 InvalidResponseLengthException。我正在使用 taplinx 库版本 1.5 我的代码如下所示: priv
我有一个 DESfire Ev1 1.3 版卡,我正在尝试使用 ISO7816 apdu 样式选择一个文件。 我有一个文件,有帮助 A0 A1 A2我可以使用 native 或包装模式选择它: 本国的
我想在本地模式下使用 desfire 卡进行身份验证。这是我目前的步骤: 我选择主应用程序 (AID = 0×00 0×00 0×00) 我收到来自卡片的响应(一个“挑战”,randB) 然后,在第二
我是一名优秀的程序员,十分优秀!