1. 程式人生 > >java aes CBC的填充方式發現

java aes CBC的填充方式發現

code throws pps int add 方法 fmt plaintext bst

如下的java代碼,手動對block進行填充後,使其為16的整數倍後,加密的時候竟然強行再填充了16位,我在嘗試用golang實現這段加密時,反復修改了很久,發現golang版的總是比java加密出來並base64的結果少了20位,於是把各個步驟中間結果打出來,發現並沒有什麽不同,然後嘗試在golang後面強行追加了16個填充,那麽填充什麽呢?沒錯,我就是從0x0到0x10一個一個試出來的,最後發現當填充16個0x10時,golang跟java的加密結果就完全一樣了,下面貼出golang跟java的兩個代碼:

PS: iv和key都是一模一樣的。得到一個教訓,當golang跟java在兩種相同的模式下面如果加密出來的密文不同的時候就去嘗試修改填充的方法吧,多嘗試幾次總是可以的。

java:

技術分享圖片
public static String aesEncrypt2(String appsecret, String data) throws Exception
    {
        //設置加密密鑰
        String key = appsecret.substring(16);
        System.out.println(key);
        SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
        //初始化向量
        System.out.println("md5: " + DigestUtils.md5Hex(appsecret).substring(0, 16));
        String iv 
= DigestUtils.md5Hex(appsecret).substring(0, 16); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); //設置加密模式 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //填充算法 int blockSize = cipher.getBlockSize(); byte[] dataBytes = data.getBytes();
int plaintextLength = dataBytes.length; if (plaintextLength % blockSize != 0) { plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize)); } byte[] plaintext = new byte[plaintextLength]; System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length); System.out.println("填充後長度=" + plaintext.length); for(int i = 0;i < plaintext.length; i++) System.out.print(plaintext[i] + " "); //加密 cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); byte[] encrypted = cipher.doFinal(plaintext); System.out.println(""); for(int i = 0;i < encrypted.length;i++) System.out.print(encrypted[i] + " "); System.out.println(""); return Base64.encodeBase64String(encrypted); }
View Code

golang:

技術分享圖片
func GetMD5(cipherText string) string {
    md5Ctx := md5.New()
    md5Ctx.Write([]byte(cipherText))
    cipherStr := md5Ctx.Sum(nil)
    return hex.EncodeToString(cipherStr)
}


func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    //    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    for i := 0; i < padding; i++ {
        ciphertext = append(ciphertext, 0x0)
    }
    for i := 16; i < 32; i++ {
        ciphertext = append(ciphertext, 0x10)
    }
    fmt.Println(ciphertext)
    fmt.Printf("blocksieze[%d]\n", len(ciphertext))
    //    return append(ciphertext, padtext...)
    return ciphertext
}

func AesEncrypt(secret, data string) string {
    if len(secret) < 16 {
        log.Errorf("AesEncrypt secret[%s] length less 16")
        return ""
    }
    fmt.Println(secret[16:])
    key := []byte(secret[16:])
    iv := []byte(GetMD5(secret)[:16])
    fmt.Println("md5: " + GetMD5(secret)[:16])
    block, err := aes.NewCipher(key)
    if err != nil {
        log.Errorf("key error[%v]", err)
        return ""
    }
    ecb := cipher.NewCBCEncrypter(block, iv)
    content := PKCS5Padding([]byte(data), block.BlockSize())
    crypted := make([]byte, len(content))
    ecb.CryptBlocks(crypted, content)
    fmt.Println(crypted)
    return base64.StdEncoding.EncodeToString(crypted)
}
View Code

java aes CBC的填充方式發現