如何在C#中的AES256加密和Java中的解密期间处理BadPaddingException

如何在C#中的AES256加密和Java中的解密期间处理BadPaddingException,第1张

概述我不知道为什么会出现错误.线程“主”中的异常javax.crypto.BadPaddingException:给定的最终块未正确填充.如果在解密过程中使用了错误的密钥,则会出现此类问题.我了解解密时使用了不正确的密钥会发生此错误.但是,如果查看下面的测试结果,您会发现C#和Java都是相同的(Key,IV,Salt是Base64编码的).> C#测试结

我不知道为什么会出现错误.

线程“主”中的异常javax.crypto.BadpaddingException:给定的最终块未正确填充.如果在解密过程中使用了错误的密钥,则会出现此类问题.

我了解解密时使用了不正确的密钥会发生此错误.但是,如果查看下面的测试结果,您会发现C#和Java都是相同的(Key,IV,Salt是Base64编码的).

> C#测试结果

> Java测试结果

一样!(Key,Salt)

但是会生成当前的BadpaddingException错误.可能是什么问题呢?
我正在附加我的源文件.

> C#(加密)

    class AES {            private Readonly static string keyStr = "This is Key";            private Readonly static string vector = "This is Vector";            public static Rfc2898DeriveBytes MakeKey(string password){                byte[] keyBytes = System.Text.EnCoding.UTF8.GetBytes(password);                byte[] saltBytes = SHA512.Create().ComputeHash(keyBytes);                Rfc2898DeriveBytes result = new Rfc2898DeriveBytes(keyBytes,saltBytes,65536);                return result;            }            public static Rfc2898DeriveBytes MakeVector(string vector){                byte[] vectorBytes = System.Text.EnCoding.UTF8.GetBytes(vector);                byte[] saltBytes = SHA512.Create().ComputeHash(vectorBytes);                Rfc2898DeriveBytes result = new Rfc2898DeriveBytes(vectorBytes,65536);                return result;            }            public static voID Encrypt(String inputfile,String outputfile) {                using (RijndaelManaged aes = new RijndaelManaged()){                    //Create Key and Vector                    Rfc2898DeriveBytes key = AES.MakeKey(AES.keyStr);                    Rfc2898DeriveBytes vector = AES.MakeVector(AES.vector);                    //AES256                    aes.BlockSize = 128;                    aes.KeySize = 256;                    // It is equal in java                     // Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5padding");                        aes.Mode = CipherMode.CBC;                     aes.padding = paddingMode.PKCS7;                     aes.Key = key.GetBytes(32); //256bit key                    aes.IV  = vector.GetBytes(16); //128bit block size                    //processing Encrypt                    ICryptotransform encryptor = aes.CreateEncryptor(aes.Key,aes.IV);                    byte[] encrypted;                    using (MemoryStream msEncrypt = new MemoryStream()) {                             using (CryptoStream csEncrypt = new CryptoStream(msEncrypt,encryptor,CryptoStreamMode.Write)) {                                byte[] inputBytes = file.ReadAllBytes(inputfile);                                csEncrypt.Write(inputBytes,inputBytes.Length);                            }                            encrypted = msEncrypt.ToArray();                             }                        string encodedString = Convert.ToBase64String(encrypted);                        file.WriteallText(outputfile,encodedString);                    }                }            }

> Java(解密)

    public class AES256file {        private static final String algorithm = "AES";        private static final String blockNpadding = algorithm+"/CBC/PKCS5padding";        private static final String password = "This is Key";        private static final String IV = "This is Vector";        private static IvParameterSpec ivSpec;        private static Key keySpec;        public static voID MakeKey(String password) throws NoSuchAlgorithmException,UnsupportedEnCodingException,InvalIDKeySpecException{            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");            MessageDigest digest = MessageDigest.getInstance("SHA-512");            byte[] keyBytes = password.getBytes("UTF-8");            // C# : byte[] saltBytes = SHA512.Create().ComputeHash(keyBytes);            byte[] saltBytes = digest.digest(keyBytes);            //256bit            PBEKeySpec pbeKeySpec = new PBEKeySpec(password.tochararray(),65536,256);            Key secretKey = factory.generateSecret(pbeKeySpec);            byte[] key = new byte[32];            System.arraycopy(secretKey.getEncoded(),key,32);            SecretKeySpec secret = new SecretKeySpec(key,"AES");            setKeySpec(secret);        }        public static voID MakeVector(String IV) throws NoSuchAlgorithmException,InvalIDKeySpecException{            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");            MessageDigest digest = MessageDigest.getInstance("SHA-512");            byte[] vectorBytes = IV.getBytes("UTF-8");            byte[] saltBytes = digest.digest(vectorBytes);            // 128bit            PBEKeySpec pbeKeySpec = new PBEKeySpec(IV.tochararray(),128);            Key secretIV = factory.generateSecret(pbeKeySpec);            byte[] iv = new byte[16];            System.arraycopy(secretIV.getEncoded(),iv,16);            IvParameterSpec ivSpec = new IvParameterSpec(iv);            setIvSpec(ivSpec);        }        public voID decrypt(file source,file dest) throws Exception {            Cipher c = Cipher.getInstance(blockNpadding);            c.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);            fileProcessing(source,dest,c);        }        public  voID fileProcessing(file source,file dest,Cipher c) throws Exception{            inputStream input = null;            OutputStream output = null;            try{                input = new BufferedinputStream(new fileinputStream(source));                output = new bufferedoutputstream(new fileOutputStream(dest));                byte[] buffer = new byte[input.available()];                int read = -1;                while((read = input.read(buffer)) != -1){                    output.write(c.update(buffer,read));                }                byte[] deryptedBytes = c.doFinal(buffer); // -----------------------> Error!! Showing!                 byte[] decodedBytes = Base64.getDecoder().decode(deryptedBytes);                String decodeString = new String(decodedBytes,"UTF-8");                decodedBytes = decodeString.getBytes(StandardCharsets.UTF_8);                output.write(decodedBytes);            }finally{                if(output != null){                    try{output.close();}catch(IOException e){}                }                if(input != null){                    try{input.close();}catch(IOException e){}                }            }        }

我已验证如下.

> C#中的验证密钥和IV

    //Key Verification        var salt = Convert.ToBase64String(saltBytes);                Console.Write("Salt Result : ");                Console.Writeline(salt);        var result_test = Convert.ToBase64String(result.GetBytes(32));                Console.Write("Key Test Result: ");                Console.Writeline(result_test);    //IV Verification (Salt is Using same code)        var result_test = Convert.ToBase64String(result.GetBytes(16));                Console.Write("IV Test Result: ");                Console.Writeline(result_test);

> Java验证密钥和IV

    //Key Verification        /* print Salt */        String base64 = Base64.getEncoder().encodetoString(saltBytes);        System.out.println("Salt Result : " + base64);        /* print Key */        String result_test = Base64.getEncoder().encodetoString(key);        System.out.println("Key Test Result : " + result_test);        /* print generated Key */        System.out.println("Secret Key Result : " + Base64.getEncoder().encodetoString(secret.getEncoded()));    //IV Verification (Salt is Using same code)        /* print IV */        String result_test = Base64.getEncoder().encodetoString(iv);        System.out.println("IV Test Result : " + result_test);        /* print generated IV */        System.out.println("IV Result : " + Base64.getEncoder().encodetoString(ivSpec.getIV()));

更新

c#.netframework 4.5 / Java8修改了@topaco所说的内容,并确认它运行良好.

我想对@topaco和@ Gusto2表示非常感谢,我将对安全性已修改的部分进行更改,就像@ Gusto2所说的一样!

最佳答案1)在C#加密方法中,首先对纯文本进行加密,然后对Base64进行编码.因此,在解密过程中,必须先对数据进行Base64解码,然后再进行解密.当前,这是以错误的顺序处理的,即数据首先被解密然后被解码.因此,在Java fileProcessing-method中替换

while((read = input.read(buffer)) != -1){    output.write(c.update(buffer,read));}

while((read = input.read(buffer)) != -1) {    byte[] bufferEncoded = buffer;    if (read != buffer.length) {         bufferEncoded = Arrays.copyOf(buffer,read);    }    byte[] bufferDecoded = Base64.getDecoder().decode(bufferEncoded);    output.write(c.update(bufferDecoded));}

2)不必将缓冲区(或bufferDecoded)传递给doFinal方法,因为这已在update-method中完成.从而,

byte[] deryptedBytes = c.doFinal(buffer);

必须替换为

output.write(c.doFinal());

3)由于已经在1)的try块中完成了Base64解码,因此必须删除doFinal语句之后的所有行.总体而言,这导致

try {    input = new BufferedinputStream(new fileinputStream(source));    output = new bufferedoutputstream(new fileOutputStream(dest));    byte[] buffer = new byte[input.available()];    int read = -1;    while((read = input.read(buffer)) != -1) {        byte[] bufferEncoded = buffer;        if (read != buffer.length) {             bufferEncoded = Arrays.copyOf(buffer,read);        }        byte[] bufferDecoded = Base64.getDecoder().decode(bufferEncoded);        output.write(c.update(bufferDecoded));    }    output.write(c.doFinal()); }

4)缓冲区的大小必须为4的倍数,以确保正确的Base64解码.因此,更换更可靠

byte[] buffer = new byte[input.available()];

byte[] buffer = new byte[4 * (input.available() / 4)];

只要以一个块读取数据(这是不能保证的,例如参见https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html#available()),就没有问题.但是,如果以多个块读取数据,则读取4个字节的倍数很重要,否则Base64解码将失败.通过使用不是4的倍数的缓冲区大小,可以很容易地证明这一点.如果针对较大的文件明确定义了缓冲区大小,则也必须考虑这一点. 总结

以上是内存溢出为你收集整理的如何在C#中的AES256加密和Java中的解密期间处理BadPaddingException 全部内容,希望文章能够帮你解决如何在C#中的AES256加密和Java中的解密期间处理BadPaddingException 所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1244303.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存