Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/179.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java/Android-使用4字节麦克风解密AES/CCM_Java_Android_Encryption_Bluetooth_Aes - Fatal编程技术网

Java/Android-使用4字节麦克风解密AES/CCM

Java/Android-使用4字节麦克风解密AES/CCM,java,android,encryption,bluetooth,aes,Java,Android,Encryption,Bluetooth,Aes,我试图解密一些由blueooth模块加密的测试数据。蓝牙固件是用C语言编程的,如果需要的话 加密的数据是: // Test Bytes - 16 bytes byte[] testInput = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; // Test key - 16 bytes, 128-bit b

我试图解密一些由blueooth模块加密的测试数据。蓝牙固件是用C语言编程的,如果需要的话

加密的数据是:

// Test Bytes - 16 bytes
byte[] testInput = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

// Test key - 16 bytes, 128-bit
byte[] keyBytes = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                   0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

// Test nonce - 13 bytes, 104-bit
byte[] nonce = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
                0x0a,0x0b,0x0c};
问题出在这里。使用AES/CCM对C中的数据进行加密,会产生一个16字节的输出,带有一个4字节的麦克风。当我在Java中使用AES/CCM/NoPadding加密数据时,输出也是16字节,但有一个8字节的MAC。MAC和MIC这两个术语似乎不明确,其中MIC用于蓝牙术语

当我用Java加密上面的testInput时,我得到与C编程加密相同的16字节输出。但是,由于麦克风和MAC的长度不同,我无法解密两端的数据

有解决办法吗

我已经添加了我的Java代码:

Cipher cipher = Cipher.getInstance("AES/CCM/NoPadding", "BC");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(nonce);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(testInput);

// The first 16 bytes print out equivalently with the C-language AES/CCM
下面是我的输出图像:

下面是C输出的图像

易读广告包


编辑:我使用的是选定的答案,但也请看Matthew Beckler的答案。它将提供更深入的答案,并防止以后出现错误。

以下Java代码将产生与C代码相同的输出:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Security;

public class Main {

    // Test Bytes - 16 bytes
    static byte[] testInput = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

    // Test key - 16 bytes, 128-bit
    static byte[] keyBytes = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

    // Test nonce - 13 bytes, 104-bit
    static byte[] nonce = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
            0x0a, 0x0b, 0x0c};


    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        GCMParameterSpec parameterSpec = new GCMParameterSpec(32, nonce);
        Cipher cipher = Cipher.getInstance("AES/CCM/NoPadding");
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, parameterSpec);
        cipher.updateAAD(new byte[]{0x01});
        System.out.println(DatatypeConverter.printHexBinary(cipher.doFinal(testInput)));
    }
}

但是,我不确定如何找到提供给Cipher.updateAAD的字节。通过反复试验发现0x01。试图阅读蓝牙4.0规范是相当痛苦的。规范似乎说字节是数据包头的第一个字节,NESN、SN、MD中的3位被强制为零。剩下的部分我仍在努力找出。

以下Java代码将产生与C代码相同的输出:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Security;

public class Main {

    // Test Bytes - 16 bytes
    static byte[] testInput = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

    // Test key - 16 bytes, 128-bit
    static byte[] keyBytes = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

    // Test nonce - 13 bytes, 104-bit
    static byte[] nonce = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
            0x0a, 0x0b, 0x0c};


    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        GCMParameterSpec parameterSpec = new GCMParameterSpec(32, nonce);
        Cipher cipher = Cipher.getInstance("AES/CCM/NoPadding");
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, parameterSpec);
        cipher.updateAAD(new byte[]{0x01});
        System.out.println(DatatypeConverter.printHexBinary(cipher.doFinal(testInput)));
    }
}

但是,我不确定如何找到提供给Cipher.updateAAD的字节。通过反复试验发现0x01。试图阅读蓝牙4.0规范是相当痛苦的。规范似乎说字节是数据包头的第一个字节,NESN、SN、MD中的3位被强制为零。我仍在努力找出剩余的位。

我已经找到了如何在计算机上使用软件加密库复制BLE样式的AES CCM。这里有更多的细节,但问题的关键是BLE CCM指定了ADATA附加数据的一个字节,该数据包含在MAC计算中,但未作为有效负载的一部分进行加密。BLE规范规定该字节必须等于数据通道PDU头的第一个八位字节,NESN、SN和MD位屏蔽为0。这意味着ADATA字节是0、1、2或3中的一个,基于数据信道PDU报头的两个LLID位,该数据信道PDU报头应可用于解密有效负载的任何设备

BLE规范提供了LLID值的描述:

00b=保留供将来使用 01b=LL Data PDU:L2CAP消息的延续片段或空PDU 10b=LL Data PDU:启动L2CAP消息或无碎片的完整L2CAP消息 11b=LL控制PDU 使用cipher.updateaaddnew byte[]{0x01},您似乎已经完成了99%的任务;在先前的回答中指出。您应该能够从数据包结构中较早的位置提取该0x01值。您可能需要屏蔽数据包字节的某些位&0xE3将这样做,以便为cipher.updateAAD调用找到正确的字节


希望这能有所帮助,如果您需要更多详细信息,我很乐意回答您的问题。

我已经知道如何在计算机上使用软件加密库复制BLE样式的AES CCM。这里有更多的细节,但问题的关键是BLE CCM指定了ADATA附加数据的一个字节,该数据包含在MAC计算中,但未作为有效负载的一部分进行加密。BLE规范规定该字节必须等于数据通道PDU头的第一个八位字节,NESN、SN和MD位屏蔽为0。这意味着ADATA字节是0、1、2或3中的一个,基于数据信道PDU报头的两个LLID位,该数据信道PDU报头应可用于解密有效负载的任何设备

BLE规范提供了LLID值的描述:

00b=保留供将来使用 01b=LL Data PDU:L2CAP消息的延续片段或空PDU 10b=LL Data PDU:启动L2CAP消息或无碎片的完整L2CAP消息 11b=LL控制PDU 使用cipher.updateaaddnew byte[]{0x01},您似乎已经完成了99%的任务;在先前的回答中指出。您应该能够从数据包结构中较早的位置提取该0x01值。您可能需要屏蔽数据包字节的某些位&0xE3将这样做,以便为cipher.updateAAD调用找到正确的字节


希望这能有所帮助,如果您需要更多详细信息,我很乐意回答您的问题。

对于蓝牙,麦克风由3个附加字节计算-0x00、0x01和一个从PDU头的第一个字节计算的字节。没有那个字节,你就不能得到相同的麦克风。@JamesKPolk你建议我如何来回传递数据?几天来我一直在寻找解决办法。如果你能进一步帮助我,我将不胜感激

必须弄清楚麦克风是如何产生的/你想加密什么?蓝牙在这里扮演什么角色?您是想解密通过配对加密的BLE数据包,还是只解密任意数据,并且能够在BLE芯片中重用CCM引擎?MIC不是解密算法的输入,而是当接收器根据nonce、key和AAD验证接收到的数据时应匹配的签名。对于蓝牙,MIC通过3个额外字节计算-0x00、0x01和从PDU头的第一个字节计算的字节。没有那个字节,你就不能得到相同的麦克风。@JamesKPolk你建议我如何来回传递数据?几天来我一直在寻找解决办法。如果您能进一步帮助我,我将不胜感激。首先,我必须弄清楚麦克风是如何产生的/您想加密什么?蓝牙在这里扮演什么角色?您是想解密通过配对加密的BLE数据包,还是只解密任意数据,并且能够在BLE芯片中重用CCM引擎?MIC不是解密算法的输入,而是当接收器根据nonce、key和AAD验证接收到的数据时应该匹配的签名。虽然0x01是这次头的第一个字节,但我们是否要假设总是这样?@FoxDonut:不,我认为有三个可能的值,1、2、,三,。但是规范是相当混乱的。你有权访问标题吗?我的工程师控制代码的C部分。我会让他给我发他能发的任何头球。有什么我应该特别要求的吗?我不确定是否有帮助,但我添加了一张广告包的图片。我删除了所有的机密信息,但你会明白的。我打开了我的工程师文件,你只能看到广告数据0部分的前3行,然后是完整的广告数据1部分。我不知道如何绕过他的IDE,但我能够获得这么多。让我知道这是否有帮助。虽然0x01是这次头的第一个字节,但我们是否应该假设应该始终是这样?@FoxDonut:不,我认为有三个可能的值,1、2和3。但是规范是相当混乱的。你有权访问标题吗?我的工程师控制代码的C部分。我会让他给我发他能发的任何头球。有什么我应该特别要求的吗?我不确定是否有帮助,但我添加了一张广告包的图片。我删除了所有的机密信息,但你会明白的。我打开了我的工程师文件,你只能看到广告数据0部分的前3行,然后是完整的广告数据1部分。我不知道如何绕过他的IDE,但我能够获得这么多。如果有帮助,请告诉我。谢谢你的帖子。我现在用上面的答案工作,但我会看看我是否能从广告包中抽出那一点,所以如果有任何变化,那么它仍然会工作!伟大的发现!谢谢你的来信。我现在用上面的答案工作,但我会看看我是否能从广告包中抽出那一点,所以如果有任何变化,那么它仍然会工作!伟大的发现!