zoukankan      html  css  js  c++  java
  • 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]
    ", 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
  • 相关阅读:
    django class类即视图类添加装饰器的几种方法
    django 如何在HMTL中使用媒体media_url
    django 对models中上传的文件或图片改名
    常用工具链接网址
    verifycode验证码模版
    shell 一些常用命令
    用 openresty 编写 lua
    centos7 安装python虚拟环境
    django url配置-反向解析-视图函数-HttpRequest对象-HttpResponse对象-cookies-session-redis缓存session
    PWN题搭建
  • 原文地址:https://www.cnblogs.com/xiaxiaosheng/p/8083295.html
Copyright © 2011-2022 走看看