2011-06-27 77 views
3

我使用AES算法来加密我的数据。当我加密16个字节(一个块)时,结果是32个字节。我期望16个字节,但它会生成32个字节。 如果我以字符串格式使用我的代码,结果是一样的。 为什么?加密(AES)

我的源代码是

package chert.chert; 

import chert.chert.R; 
import chert.chert.SimpleCrypto; 
import android.app.Activity; 
import android.os.Bundle; 
import android.widget.TextView; 

public class ChertActivity extends Activity { 
    /** Called when the activity is first created. */ 
    TextView textView1; 



    byte[] key=new byte[16]; 
    byte[] state=new byte[16]; 
    public SimpleCrypto Crypt = new SimpleCrypto(this); 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     int i; 
     String ss,state_str,key_str; 
     char c; 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 




     //======================================================================================================================   

     state[0]=0x32;   state[1]=(byte) 0x88; state[2]=0x31;   state[3]=(byte) 0xe0; 
     state[4]=0x43;   state[5]=0x5a;   state[6]=0x31;   state[7]=0x37; 
     state[8]=(byte) 0xf6; state[9]=0x30;   state[10]=(byte) 0x98; state[11]=0x07; 
     state[12]=(byte) 0xa8; state[13]=(byte) 0x8d; state[14]=(byte) 0xa2; state[15]=0x34; 


    //======================================================================================================================   

     key[0]=0x2b;   key[1]=0x28;    key[2]=(byte) 0xab; key[3]=0x09; 
     key[4]=0x7e;   key[5]=(byte) 0xae;   key[6]=(byte) 0xf7; key[7]=(byte) 0xcf; 
     key[8]=0x15;   key[9]=(byte) 0xd2;   key[10]=0x15;   key[11]=0x4f; 
     key[12]=0x16;   key[13]=(byte) 0xa6;  key[14]=(byte) 0x88; key[15]=0x3c; 

     //======================================================================================================================   

     try { 
      byte[] rawKey = Crypt.getRawKey(key); 
      byte[] result = Crypt.encrypt(rawKey, state); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

    } 
} 







package chert.chert; 
import java.security.SecureRandom; 

import javax.crypto.Cipher; 
import javax.crypto.KeyGenerator; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.SecretKeySpec; 

public class SimpleCrypto { 

    public SimpleCrypto(ChertActivity chertActivity) { 
     // TODO Auto-generated constructor stub 
    } 

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

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


    public 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 { 
     SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
     Cipher cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
     byte[] decrypted = cipher.doFinal(encrypted); 
     return decrypted; 
    } 

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

} 
+1

我删除我的答案学习密码默认使用EBC模式加密后(!),而不是CBC模式(或类似的东西)。然而,这又提出了另一个问题:你几乎肯定希望覆盖这个默认值,因为EBC对这个词的最合理的形式定义是不安全的。例如,拦截EBC模式加密消息的人可以轻易地判断消息(或实际上是消息内的块)是否重复,或者(在没有正确实施的MAC中)任意重新排列块。当然,这些东西有多么有害取决于环境。 – Seth

+0

@Seth:欧洲央行,而不是EBC。但我们知道你的意思:) –

回答

5

如果明文的长度是块的大小的倍数,需要一种用于根据PKCS#5填充一个全新的块。说你的明文是16字节。密文将占用32个字节。

它是像下面

CipherTextLength = (PlainTextLength/16 + 1) * 16; 
+1

更具体地说,默认模式PKCS5Padding总是添加*至少*一个填充字节,并且总是增加到四舍五入为16字节的块长度的倍数。 –

+1

你说得对。 Cipher的长度=(inserteddataLength/16 + 1)* 16; 但有一个问题。如果你输入16个字节进行加密,你可以获得32个字节,但你需要16个字节,这32个字节不是你的答案。 如果你输入32个字节,你可以在结果中获得48个字节,但你只需要32个字节。 – mosbate

+0

WOOW 我的问题解决了。 特别感谢Sunil Kumar。 – mosbate