我不知道为什么会出现错误.
线程“主”中的异常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 所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)