2012-08-02 28 views
0

我遇到了一個很大的問題,我開發了一個應用程序,它使用加密技術將消息發送到其他設備。SecureRandom及其不同的提供商

這裏密碼類,我「偷」這一點,但我不記得在哪裏:

public class AesCipher { 
    public static String encrypt(String seed, String cleartext) throws Exception { 
     byte[] rawKey = getRawKey(seed.getBytes()); 
     byte[] result = encrypt(rawKey, cleartext.getBytes()); 
     return toHex(result); 
    } 

    public static String decrypt(String seed, String encrypted) throws Exception { 
     byte[] rawKey = getRawKey(seed.getBytes()); 
     byte[] enc = toByte(encrypted); 
     byte[] result = decrypt(rawKey, enc); 
     return new String(result); 
    } 

    private static byte[] getRawKey(byte[] seed) throws Exception { 
     KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
     SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
     sr.setSeed(seed); 
     kgen.init(256,sr); // 192 and 256 bits may not be available 
     SecretKey skey = kgen.generateKey(); 
     byte[] raw = skey.getEncoded(); 
     return raw; 
    } 


    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { 
     SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
     Cipher cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
     byte[] encrypted = cipher.doFinal(clear); 
     return encrypted; 
    } 

    private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { 
     try{ 
      SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
      Cipher cipher = Cipher.getInstance("AES"); 
      cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
      byte[] decrypted = cipher.doFinal(encrypted); 
      return decrypted; 
     } 
     catch (Exception e) {return encrypted;} 
    } 

    public static String toHex(String txt) { 
     return toHex(txt.getBytes()); 
    } 
    public static String fromHex(String hex) { 
     return new String(toByte(hex)); 
    } 

    public static byte[] toByte(String hexString) { 
     int len = hexString.length()/2; 
     byte[] result = new byte[len]; 
     for (int i = 0; i < len; i++) 
      result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); 
     return result; 
    } 

    public static String toHex(byte[] buf) { 
     if (buf == null) 
      return ""; 
     StringBuffer result = new StringBuffer(2*buf.length); 
     for (int i = 0; i < buf.length; i++) { 
      appendHex(result, buf[i]); 
     } 
     return result.toString(); 
    } 
    private final static String HEX = "ABCDEF"; 
    private static void appendHex(StringBuffer sb, byte b) { 
     sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f)); 
    } 
} 

所以,如果我將消息發送到同一個設備,我的應用程序工作正常,但如果我使用不同的設備版本(andorid2.3 vs android4.0),接收器不能解密消息。

搜索我發現問題是SecureRandom,它不能保證不同實現的兼容性。我如何解決它?

對不起,我的英語...

回答

1

是的,我一直試圖讓那個可怕的示例中刪除,但無濟於事。

您應該嘗試從2.3設備檢索字節,並使用生成的raw[]字節數組創建SecretKeySpec。您可以直接使用此SecretKeySpec作爲密鑰來解密您在2.3設備上加密的任何內容。

不幸的是,如果您使用4設備加密任何東西並「扔掉」raw[],那麼您唯一的選擇是打破"AES/ECB/PKCS5Padding"(使用"AES"時的默認設置)。你也許能從ECB模式中獲得一小部分信息,因爲這也是不安全的,但是否則它會降低到打破AES密文安全 - 而且據我們所知,這個世界上沒有人能夠做到這一點。

+0

解決方案是否正確?我已經用MD5 hasing('MessageDigest.getInstance(「MD5」)')替換了所有'getRawKay'方法實現(因此'KeyGenerator'和'SecureRandom')...通信可以正常使用這種方法...並且安全工作也很好; )? – Ging3r 2012-08-03 15:09:40

+0

這取決於種子。如果它是密碼,我建議你改用PBKDF2。如果它是(接近)隨機的話,你很好,儘管SHA-256會更有意義。 – 2012-08-03 21:07:53