2017-09-26 1 views
1

Je tente de décrypter certaines données de test chiffrées par un module blueooth. Le firmware du bluetooth est programmé en C, si cela est important.Java/Android - Décryptage AES/CCM avec un MIC de 4 octets

Les données chiffrées ont été:

// 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}; 

est ici le problème. Le cryptage des données en C, en utilisant AES/CCM, produit une sortie de 16 octets, avec un MIC de 4 octets. Lorsque je crypte les données en utilisant AES/CCM/NoPadding en Java, la sortie est également de 16 octets, mais a un MAC de 8 octets. Les termes MAC et MIC sont ambigus, semble-t-il, où MIC est utilisé pour la terminologie bluetooth.

Lorsque je crypte le testInput ci-dessus en Java, j'obtiens les mêmes 16 octets de sortie que le cryptage de programmation C. Mais, étant donné que MIC et MAC ont des longueurs différentes, je ne peux pas déchiffrer les données à chaque extrémité.

Y at-il une solution à cela?

J'ai ajouté mon code 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 

est Ci-dessous une image de ma sortie:

enter image description here

est Ci-dessous une image de la sortie C.

enter image description here

BLE Publicité Packet

enter image description here

+1

Pour le Bluetooth, le MIC est calculé sur 3 octets supplémentaires - 0x00, 0x01 et un octet qui est calculé à partir du premier octet de l'en-tête PDU. Sans cet octet, vous ne pouvez pas obtenir le même MIC. –

+0

@JamesKPolk Comment suggérez-vous que je transmette des données? J'ai cherché une solution pendant des jours. Je serais extrêmement reconnaissant si vous pouviez m'aider plus loin. – FoxDonut

+1

D'abord, je dois comprendre comment le MIC a été généré/ –

Répondre

1

Le code Java suivant produira le même résultat que le code 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))); 
    } 
} 

Cependant, je ne suis pas sûr pour trouver l'octet à fournir à Cipher.updateAAD(). 0x01 a été trouvé par des essais et erreurs. Essayer de lire la spécification Bluetooth 4.0 est assez douloureux. La spécification semble indiquer que l'octet est le premier octet de l'en-tête du paquet, avec 3 des bits (NESN, SN, MD) forcés à zéro. Les bits restants que j'essaie encore de comprendre.

+0

Bien que 0x01 soit le premier octet de l'en-tête cette fois-ci, devons-nous supposer que cela devrait toujours être le cas? – FoxDonut

+0

@FoxDonut: Non, je pense qu'il y a trois valeurs possibles, 1, 2 et 3. Mais la spécification est assez déroutante. Avez-vous accès à l'en-tête? –

+0

Mon ingénieur contrôle la partie C du code. Je vais lui demander de m'envoyer tout ce qu'il peut pour l'en-tête. Quelque chose que je devrais demander spécifiquement? – FoxDonut