java aes CBC的填充方式发现

如下的java代码,手动对block进行填充后,使其为16的整数倍后,加密的时候竟然强行再填充了16位,我在尝试用golang实现这段加密时,反复修改了很久,发现golang版的总是比java加密出来并base64的结果少了20位,于是把各个步骤中间结果打出来,发现并没有什么不同,然后尝试在golang后面强行追加了16个填充,那么填充什么呢?没错,我就是从0x0到0x10一个一个试出来的,最后发现当填充16个0x10时,golang跟java的加密结果就完全一样了,其实是按照pkcs5的填充规则的,例如需要填充n位,那么填充的值就是n,下面贴出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

 

转载于:https://www.cnblogs.com/xiaxiaosheng/p/8083295.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你需要使用Java进行AES CBC解密,并且需要使用0填充,可以使用以下代码: ```java import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class AESCBCDecrypt { public static void main(String[] args) throws Exception { byte[] key = "0123456789abcdef".getBytes("UTF-8"); byte[] iv = "0123456789abcdef".getBytes("UTF-8"); byte[] encrypted = hexStringToByteArray("7f5d8d9dceb05d9a4a9d2a8a9e8c2c9b"); // Create the key specification and the initialization vector specification SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(iv); // Create the cipher object and initialize it with the key and initialization vector Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); // Decrypt the ciphertext byte[] decrypted = cipher.doFinal(encrypted); // Print the decrypted plaintext System.out.println(new String(decrypted, "UTF-8")); } // Helper function to convert a hex string to a byte array public static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return data; } } ``` 在上面的代码中,我们使用AES/CBC/NoPadding模式进行解密,这意味着我们需要手动添加填充。在这种情况下,我们使用0字节作为填充字符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值