AES加密没问题!解密时出错了!

ania6 2011-04-09 12:36:50
package serictly;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import sun.misc.resources.*;;
public class EncrypImpl implements Encryp{
public byte[] decryption(String s) {
KeyGenerator keygen;
SecretKey deskey = null ;
Cipher c = null ;
byte[] enc=null;
try {
keygen = KeyGenerator.getInstance("AES");
deskey = keygen.generateKey();
try {
c = Cipher.getInstance("AES");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
String msg =s;
System.out.println("文明是:"+msg);
try {
c.init(Cipher.ENCRYPT_MODE, deskey);
byte[] src = msg.getBytes();
try {
enc = c.doFinal(src);
System.out.println("+++"+enc);
System.out.println("密文是:"+new String(enc));
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return enc;
}
public String encryption(byte[] s) {
KeyGenerator keygen;
SecretKey deskey = null ;
Cipher c = null ;
System.out.println(s);
try {
keygen = KeyGenerator.getInstance("DESede");
deskey = keygen.generateKey();
try {
c = Cipher.getInstance("DESede");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
c.init(Cipher.DECRYPT_MODE, deskey);
try {
byte[] dec = c.doFinal(s);
System.out.println("文明是:"+new String (dec));
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
}在加密时就没错误,但是解密时就错误了,
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.DESedeCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at serictly.EncrypImpl.encryption(EncrypImpl.java:88)
at serictly.s.main(s.java:14)
...全文
3006 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
qingkangxu 2011-04-16
  • 打赏
  • 举报
回复
楼主加密解密的基础知识还需要学习啊
1,从你设计的类方法来看,就搞混了加密和解密的概念。合符常情的概念是:通常加密的参数应该是原文(也就是String类型),加密的返回值是密文字节;解密的参数应该是密文字节,返回值是原文//这一点倒是没啥
2,也就是你出错的原因,你的两个方法,加密和解密用的加密方法都不一样,相信你测试的时候是encryption("xxx".getBytes());decryption("xxx")。这肯定是要出错的,加解密的算法都必须是一样的(比如要么你就是DESede,要么就是AES),解密的时候你随便输参数是不行的,因为字节数啥的都必须符合加解密算法的字节要求,只有用相同的算法加密得到的字节数才符合相同算法解密时的字节数要求,简而言之就是一个填充的问题(padding),字节数不够的时候,加解密算法是要自己填充的,你xxx的字节数肯定不符合啊。 比较啰嗦,你好好理解。
3,也是个致命的错误,你在加解密方法都生成加解密用的key了,keygen.generateKey();这也是不行的,加解密都必须用相同的key,因此你这里需要用一个实例变量解决共用同一个key

基于以上,楼下给你一个例子
ania6 2011-04-16
  • 打赏
  • 举报
回复
3楼谢谢啦
qingkangxu 2011-04-16
  • 打赏
  • 举报
回复
很简单的程序,被你写得还复杂哦,记住关键字(加解密算法必须相同/加解密使用的key必须相同/解密的字节必须是相同算法加密过的)
1,实现类,把你颠倒的方法掉正为正常思维逻辑的了(加解密的方法参数和返回值类型跟你的相反)
package security.crypt.aes;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

/**
* 如果還需要改進的話,還可以增加設置加解密算法的方法
* @author sta
*
*/
public class EncrypImpl implements Encryp {
SecretKey deskey = null;// 加解密必须使用相同的key,所以需要用实例变量控制

public String decryption(byte[] s) {
System.out.println("解密开始...");
Cipher c = null;
byte[] enc = null;
try {
// c = Cipher.getInstance("DESede");
c = Cipher.getInstance("AES");
} catch (Exception e) {
e.printStackTrace();
}

try {
c.init(Cipher.DECRYPT_MODE, deskey);
enc = c.doFinal(s);
System.out.println("\t解密之后的明文是:" + new String(enc));
} catch (Exception e) {
e.printStackTrace();
}
return new String(enc);
}

public byte[] encryption(String s) {
System.out.println("加密开始...");
System.out.println("\t原文:" + s);
KeyGenerator keygen;
Cipher c = null;
try {
// keygen = KeyGenerator.getInstance("DESede");
keygen = KeyGenerator.getInstance("AES");
deskey = keygen.generateKey();
// c = Cipher.getInstance("DESede");
c = Cipher.getInstance("AES");
} catch (Exception e) {
e.printStackTrace();
}
byte[] dec = null;
try {
c.init(Cipher.ENCRYPT_MODE, deskey);
dec = c.doFinal(s.getBytes());
System.out.print("\t加密后密文是:");
for (byte b : dec) {
System.out.print(b + ",");
}
System.out.println();
} catch (Exception e) {
e.printStackTrace();
}
return dec;
}
}


2,测试类
package security.crypt.aes;

public class Tester {

/**
* @param args
*/
public static void main(String[] args) {
Encryp encryp = new EncrypImpl();
String str ="abc";
byte[] de = encryp.encryption(str);
String str1 = encryp.decryption(de);
}

}
ania6 2011-04-14
  • 打赏
  • 举报
回复
这就是完整的啦
还有个测试就简单一个main函数呀
goodmrning 2011-04-09
  • 打赏
  • 举报
回复
代码完整贴出。
有想过,像使用U盘一样升级STM32固件,非常简单,非常方便 1: 插入电脑USB接口 2: 把升级固件拖到设备盘符 3: 升级完成 抛弃繁琐的USB DFU,抛弃落后的串口升级,让我们来谈谈U盘升级STM32 1. 为什么设计这个BOOT LOADER 在电子产品开发过程中,为了满足市场需要,经常是先开发出一个简单可用的版本,然后逐步迭代升级,修复bug,并增强系统功能 一个稳定,简单,安全的升级方式,就变得非常重要 对于嵌入式系统来说,常见的升级方式为 串口升级(私有协议或者X-Modem) USB升级(DFU) U盘升级(OTG) 网络升级 无线升级(OTA) 从技术来说,这几种升级方式大同小异,原理类似:都是一个Loader代理接收数据通道的数据,然后解密,烧录到FLASH中;但用户体验完全不同,拿串口升级来说,首先用户需要一个串口软件,然后对于有硬件串口的PC来说,就需要一个USB转串口设备,对于不同PC平台,串口软件就不一样,这需要学习成本,过程繁琐;所以在一些需要用户自行升级远程设备的情况下,即便是通过电话指导,80%的用户仍然不知道怎么升级,导致失败 USB的DFU升级,也是类似的问题,它设计的初衷就是面向专业用户的,而不是小白!所以需要安装DFU软件,按照手册来一步步升级 OTA升级和网络升级,体验好些,可用做到无感升级,但不适合所有场景 而U盘升级,用户学习成本最低,U盘大家都知道,然后拷贝一个Bin文件进去,插入设备,重启设备,就完成升级了,非常简单。类似的变种,比如手机升级,是最先进的,直接将手机模拟成U盘,然后用户拷贝数据到手机,重启就好了,非常简单 在嵌入式系统中,还这么方便的升级手段,虽然ARM的Mbed有一种类似的固件更新功能,但它是专门为调试器设计的,不能内嵌到用户MCU中 所以,我将手机升级的方案引入到嵌入式系统中,从而为大家提供一个实现稳定,安全,零学习成本的升级方案 经过一段间的学习研究,有了这个USB MSD Bootloader 2. 功能特点 只占用15K FLASH空间 简单易用,直接拖拽文件进行固件升级,无需任何专业知识 采用USB大容量设备类,不用安装任何驱动 支持各种系统(Windows/Linux/Mac/Android) 不用开发任何上位机,提高产品效率 支持各种加密算法(AES256等),轻松安全升级 自动识别Bin,Hex,自定义加密固件(后缀为sec)文件 支持MD5文件校验机制,保证固件升级的完整性 显示设备升级状态信息 支持长文件名升级 多种措施保证系统健壮性,保证Bootloader不会被误擦除,保证APP合法性 支持用户自定义加密算法和完整校验算法,极致安全 3. 系统原理 系统开机上电后,Bootloader接管系统,初始化USB硬件,等待USB连接 Bootloader在启动后1秒内,检测USB是否连接PC:如果连接PC,则进入固件升级模式,执行第3步;超则跳转第8步,尝试执行用户APP Bootloader模拟成MSD设备,构建FAT16虚拟文件系统,U盘名为”Bootloader”,容量为100M,但具体实际可用空间,根据用户MCU来确定,建议不要复制除APP之外的无关文件 当用户复制文件到U盘,Bootloader会判断文件后缀和判断文件size,如果size大于实际的MCU可用FLASH或者文件后缀不合法,则进入错误状态,更新状态文件,重新枚举USB 文件后缀和size通过检测后,Bootloader会截获PC发送文件数据流,并写入MCU 对应的Flash中 如果写入过程中出错,则终止操作,擦除APP内容,进入错误状态,更新状态文件,重新枚举USB 成功写入后,Bootloader更新状态文件,重新枚举USB,显示升级完成;但不会运行APP,只有拔掉USB后,再次重启,才会进入第8步,尝试运行APP Bootloader检查APP固件的栈和入口函数合法性,只有通过检测后,才开始执行APP。检测判断条件是栈指针必须在RAM地址空间内,入口函数地址必须处于THUMB模式,并LSB为1 停止USB设备,关掉所有的中断,执行APP,APP开始接管系统 4. 支持芯片 STM32F101/3/5/7 重点来了,点击下面链接,下载固件

51,396

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧