2013-07-10 42 views
2

我开发了一个在飞思卡尔FRDM-KL25Z(Cortex-M0)板上运行的嵌入式应用程序,通过ADB(Android调试桥)协议连接Android手机(HTC Tattoo)。如何支持与MCU的ADB认证?

但是Google最近通过v4.2.2(Jelly bean)通过USB ADB实施了RSA认证,以提高安全性。这意味着我的设计仅支持从v1.5到v4.2.1的Android设备。

在A_CNXN消息期间,从我的Galaxy Nexus答复的A_AUTH消息将我的RSA(密钥)作为黑名单。

我无法找到有关ADB接口中使用的所有RSA认证的足够信息。如密钥长度,密钥存储位置等。我找不到描述实现细节的相关文档。

可以在嵌入式ARM MCU上部署RSA身份验证吗?到目前为止,我发现LPC1343(cortex-M3)的实现具有有限长整数到RSA计算(64位)。然而,RSA在商业认证算法中至少使用512位计算。

如果不是,那么我必须改变我的设计,以支持ADK/AOA在同一时间。但AOA/ADK在v2.3.7之前不支持较旧的设备。它使事情变得更加复杂,至少我在Android上运行的应用程序应该用两种方法开发。

真是一团糟。

回答

-1

Heyho,我知道,这个问题真的很老......但是,我发现了一些可以帮助你的东西。

这是一个用于签署ADB A_AUTH令牌的java代码片段。

希望这有助于ü;)

来源:http://www.java2s.com/Open-Source/Android_Free_Code/Hardware/usb/com_cgutman_adblibAdbCrypto_java.htm

package com.cgutman.adblib; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.math.BigInteger; 
import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.security.GeneralSecurityException; 
import java.security.KeyFactory; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.NoSuchAlgorithmException; 
import java.security.interfaces.RSAPublicKey; 
import java.security.spec.EncodedKeySpec; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.PKCS8EncodedKeySpec; 
import java.security.spec.X509EncodedKeySpec; 
import javax.crypto.Cipher; 

/** 
* This class encapsulates the ADB cryptography functions and provides 
* an interface for the storage and retrieval of keys. 
* @author Cameron Gutman 
*/ 
public class AdbCrypto 
{ 

    /** An RSA keypair encapsulated by the AdbCrypto object */ 
    private KeyPair keyPair; 

    /** The base 64 conversion interface to use */ 
    private AdbBase64 base64; 

    /** The ADB RSA key length in bits */ 
    public static final int KEY_LENGTH_BITS = 2048; 

    /** The ADB RSA key length in bytes */ 
    public static final int KEY_LENGTH_BYTES = KEY_LENGTH_BITS/8; 

    /** The ADB RSA key length in words */ 
    public static final int KEY_LENGTH_WORDS = KEY_LENGTH_BYTES/4; 

    /** The RSA signature padding as an int array */ 
    public static final int[] SIGNATURE_PADDING_AS_INT = new int[] 
    { 
     0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
     0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00, 
     0x04,0x14 
    }; 

    /** The RSA signature padding as a byte array */ 
    public static byte[] SIGNATURE_PADDING; 

    static { 
    SIGNATURE_PADDING = new byte[SIGNATURE_PADDING_AS_INT.length]; 

    for (int i = 0; i<SIGNATURE_PADDING.length; i++) 
     SIGNATURE_PADDING[i] = (byte)SIGNATURE_PADDING_AS_INT[i]; 
    } 

    /** 
    * Converts a standard RSAPublicKey object to the special ADB format 
    * @param pubkey RSAPublicKey object to convert 
    * @return Byte array containing the converted RSAPublicKey object 
    */ 
    private static byte[] convertRsaPublicKeyToAdbFormat(RSAPublicKey pubkey) 
    { 
     /* 
     * ADB literally just saves the RSAPublicKey struct to a file. 
     * 
     * typedef struct RSAPublicKey { 
     * int len; // Length of n[] in number of uint32_t 
     * uint32_t n0inv; // -1/n[0] mod 2^32 
     * uint32_t n[RSANUMWORDS]; // modulus as little endian array 
     * uint32_t rr[RSANUMWORDS]; // R^2 as little endian array 
     * int exponent; // 3 or 65537 
     * } RSAPublicKey; 
     */ 

     /* ------ This part is a Java-ified version of RSA_to_RSAPublicKey from adb_host_auth.c ------ */ 
     BigInteger r32, r, rr, rem, n, n0inv; 

     r32 = BigInteger.ZERO.setBit(32); 
     n = pubkey.getModulus(); 
     r = BigInteger.ZERO.setBit(KEY_LENGTH_WORDS * 32); 
     rr = r.modPow(BigInteger.valueOf(2), n); 
     rem = n.remainder(r32); 
     n0inv = rem.modInverse(r32); 

     int myN[] = new int[KEY_LENGTH_WORDS]; 
     int myRr[] = new int[KEY_LENGTH_WORDS]; 
     BigInteger res[]; 
     for (int i = 0; i < KEY_LENGTH_WORDS; i++) 
     { 
      res = rr.divideAndRemainder(r32); 
      rr = res[0]; 
      rem = res[1]; 
      myRr[i] = rem.intValue(); 

      res = n.divideAndRemainder(r32); 
      n = res[0]; 
      rem = res[1]; 
      myN[i] = rem.intValue(); 
     } 

     /* ------------------------------------------------------------------------------------------- */ 

     ByteBuffer bbuf = ByteBuffer.allocate(524).order(ByteOrder.LITTLE_ENDIAN); 


     bbuf.putInt(KEY_LENGTH_WORDS); 
     bbuf.putInt(n0inv.negate().intValue()); 
     for (int i : myN) 
      bbuf.putInt(i); 
     for (int i : myRr) 
      bbuf.putInt(i); 

     bbuf.putInt(pubkey.getPublicExponent().intValue()); 
     return bbuf.array(); 
    } 

    /** 
    * Creates a new AdbCrypto object from a key pair loaded from files. 
    * @param base64 Implementation of base 64 conversion interface required by ADB 
    * @param privateKey File containing the RSA private key 
    * @param publicKey File containing the RSA public key 
    * @return New AdbCrypto object 
    * @throws IOException If the files cannot be read 
    * @throws NoSuchAlgorithmException If an RSA key factory cannot be found 
    * @throws InvalidKeySpecException If a PKCS8 or X509 key spec cannot be found 
    */ 
    public static AdbCrypto loadAdbKeyPair(AdbBase64 base64, File privateKey, File publicKey) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException 
    { 
     AdbCrypto crypto = new AdbCrypto(); 

     int privKeyLength = (int)privateKey.length(); 
     int pubKeyLength = (int)publicKey.length(); 
     byte[] privKeyBytes = new byte[privKeyLength]; 
     byte[] pubKeyBytes = new byte[pubKeyLength]; 

     FileInputStream privIn = new FileInputStream(privateKey); 
     FileInputStream pubIn = new FileInputStream(publicKey); 

     privIn.read(privKeyBytes); 
     pubIn.read(pubKeyBytes); 

     privIn.close(); 
     pubIn.close(); 

     KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 
     EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privKeyBytes); 
     EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(pubKeyBytes); 

     crypto.keyPair = new KeyPair(keyFactory.generatePublic(publicKeySpec), 
     keyFactory.generatePrivate(privateKeySpec)); 
     crypto.base64 = base64; 

     return crypto; 
    } 

    /** 
    * Creates a new AdbCrypto object by generating a new key pair. 
    * @param base64 Implementation of base 64 conversion interface required by ADB 
    * @return A new AdbCrypto object 
    * @throws NoSuchAlgorithmException If an RSA key factory cannot be found 
    */ 
    public static AdbCrypto generateAdbKeyPair(AdbBase64 base64) throws NoSuchAlgorithmException 
    { 
     AdbCrypto crypto = new AdbCrypto(); 

     KeyPairGenerator rsaKeyPg = KeyPairGenerator.getInstance("RSA"); 
     rsaKeyPg.initialize(KEY_LENGTH_BITS); 

     crypto.keyPair = rsaKeyPg.genKeyPair(); 
     crypto.base64 = base64; 

     return crypto; 
    } 

    /** 
    * Signs the ADB SHA1 payload with the private key of this object. 
    * @param payload SHA1 payload to sign 
    * @return Signed SHA1 payload 
    * @throws GeneralSecurityException If signing fails 
    */ 
    public byte[] signAdbTokenPayload(byte[] payload) throws GeneralSecurityException 
    { 
     Cipher c = Cipher.getInstance("RSA/ECB/NoPadding"); 

     c.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate()); 

     c.update(SIGNATURE_PADDING); 

     return c.doFinal(payload); 
    } 

    /** 
    * Gets the RSA public key in ADB format. 
    * @return Byte array containing the RSA public key in ADB format. 
    * @throws IOException If the key cannot be retrived 
    */ 
    public byte[] getAdbPublicKeyPayload() throws IOException 
    { 
     byte[] 
     convertedKey = convertRsaPublicKeyToAdbFormat((RSAPublicKey)keyPair.getPublic()); 
     StringBuilder keyString = new StringBuilder(720); 

     /* The key is base64 encoded with a [email protected] suffix and terminated with a NUL */ 
     keyString.append(base64.encodeToString(convertedKey)); 
     keyString.append(" [email protected]"); 
     keyString.append('\0'); 

     return keyString.toString().getBytes("UTF-8"); 
    } 

    /** 
    * Saves the AdbCrypto's key pair to the specified files. 
    * @param privateKey The file to store the encoded private key 
    * @param publicKey The file to store the encoded public key 
    * @throws IOException If the files cannot be written 
    */ 
    public void saveAdbKeyPair(File privateKey, File publicKey) throws IOException 
    { 
     FileOutputStream privOut = new FileOutputStream(privateKey); 
     FileOutputStream pubOut = new FileOutputStream(publicKey); 

     privOut.write(keyPair.getPrivate().getEncoded()); 
     pubOut.write(keyPair.getPublic().getEncoded()); 

     privOut.close(); 
     pubOut.close(); 
    } 
} 
0

最近我evaluted的mbed TLS(mbed-例如-TLS-基准)与STM32F401(512KB ROM/196KB RAM M4在84MHz),其基准数字显示RSA2048可以在2000ms内完成。但是它会在STM32F103RB(72MHz上的128KB ROM/20KB RAM M3)上抛出内存malloc错误。

因此我草草得出结论,M3/M4内核可以在可接受的时间窗口内支持RSA2048,但其内存是一个瓶颈。至少我们为RSA/TLS使用了32KB/64KB的RAM。