IDEA加密文件Base64转换String传输以及报文摘要MD5防止恶意篡改
2015-09-15 13:45
447 查看
一、需求:将数据加密之后存放到excel表中,到另一个地方之后,解密读出明文,但要采取一定的方法鉴别密文是否被修改过。二、思路:先用MD5报文摘或要算法算出明文的摘要信息,并把摘要信息和明文一起用IDEA进行加密,保存密文到excel表中。当要读取得时候,先解密,再分离明文和报文摘要,同时再用md5算出明文的报文摘要,用这个报文摘要和原来的摘要对比,如果一样,则密文没有被改动。三、遇到的问题:在进行加密和解密的过程中需要这样的转换:string-byte-string-byte,如果直接用jdk的普通类进行转换,是不可行的,需要借用Base64这个类。四、代码部分:[/b]1、CipherService类,用来IDEA的密钥生成、加密以及解密(可以自己定义密钥)用的的工具包是:bcprov-ext-jdk16-146.jar
import java.security.Key; import java.security.Security; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class CipherService { /** * 密钥算法 * */ public static final String KEY_ALGORITHM="IDEA"; /** * 这是加密和解密的钥匙,暂时为这个,最长为128位 */ public static final String KEY = "HELLOIAMFINLEYHA"; /** * 加密/解密算法/工作模式/填充方式 * */ public static final String CIPHER_ALGORITHM="IDEA/ECB/ISO10126Padding"; /** * * 生成密钥,只有bouncycastle支持 * @return byte[] 二进制密钥 * */ public byte[] initkey() throws Exception{ //加入bouncyCastle支持 Security.addProvider(new BouncyCastleProvider()); //实例化密钥生成器 KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM); //初始化密钥生成器,IDEA要求密钥长度为128位 kg.init(128); //生成密钥 SecretKey secretKey=kg.generateKey(); //获取二进制密钥编码形式 return secretKey.getEncoded(); } /** * 转换密钥 * @param key 二进制密钥 * @return Key 密钥 * */ public Key toKey(byte[] key) throws Exception{ //实例化iDES密钥 //生成密钥 SecretKey secretKey=new SecretKeySpec(key,KEY_ALGORITHM); return secretKey; } /** * 加密数据 * @param data 待加密数据 * @param key 密钥 * @return byte[] 加密后的数据 * */ public byte[] encrypt(byte[] data,byte[] key) throws Exception{ //加入bouncyCastle支持 Security.addProvider(new BouncyCastleProvider()); //还原密钥 Key k=this.toKey(key); //实例化 Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); //初始化,设置为加密模式 cipher.init(Cipher.ENCRYPT_MODE, k); //执行操作 return cipher.doFinal(data); } /** * 解密数据 * @param data 待解密数据 * @param key 密钥 * @return byte[] 解密后的数据 * */ public byte[] decrypt(byte[] data,byte[] key) throws Exception{ //加入bouncyCastle支持 Security.addProvider(new BouncyCastleProvider()); //还原密钥 Key k =this.toKey(key); Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); //初始化,设置为解密模式 cipher.init(Cipher.DECRYPT_MODE, k); //执行操作 return cipher.doFinal(data); } }2、excel表的导入导出,同时实现在这个过程中进行加密和解密:用到的包有:bcprov-ext-jdk16-146.jar、下面是个包是对poi对excel表的操作是用到的poi-3.12-20150511.jarpoi-ooxml-3.12-20150511.jarpoi-ooxml-schemas-3.12-20150511.jarlib/xmlbeans-2.6.0.jar本来想上传到云盘里面然后分享给大家下载的链接、、、、、、不过下载这些包也不难,建议到官网逛逛
/** * 把二维数组导出成excel表 * @param list 装载导出数据的二维数组 * @param filePath 导出的文件名,不包含路径 * @author LiangYiHuai */ public boolean exportForm(List<ArrayList<String>> list, String fileName) { try { //Windows风格 UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); } catch (Exception e1) { e1.printStackTrace(); } JFileChooser saveFileFrame = new JFileChooser(); saveFileFrame.setSelectedFile(new File(fileName)); int values = saveFileFrame.showSaveDialog(null); saveFileFrame.setDialogTitle("另存为..."); saveFileFrame.setVisible(true); if(values == 1){ return false; } String absolutePath = saveFileFrame.getSelectedFile().getAbsolutePath(); System.out.println(absolutePath); File file = new File(absolutePath); if(!file.exists()){ try { if(!file.createNewFile()){ JOptionPane.showMessageDialog(null, "文件保存失败!", "提示", 2); return false; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } }else{ if(JOptionPane.showConfirmDialog(null, "存在同名文件,确定覆盖?", "提示", JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION){ return false; } } int index = absolutePath.lastIndexOf("."); String suffix = absolutePath.substring(index + 1); boolean flag = false; Workbook wb = null; if ("xls".equals(suffix)) { wb = new HSSFWorkbook(); } else if ("xlsx".equals(suffix)) { wb = new XSSFWorkbook(); } else { return false; } Sheet sheet = wb.createSheet(); // 生成除标题行外的数据 int size = list.size(); byte[] encryptByte = null; String encryptString = ""; for (int k = 0; k < size; k++) { Row row = sheet.createRow(k); int size_2 = list.get(k).size(); for (int i = 0; i < size_2; i++) { String tempString = list.get(k).get(i); if(tempString == null){ tempString = ""; } try { *//** * 对导出的数据进行加密 *//* encryptByte = cipherService.encrypt(tempString.getBytes(), CipherService.KEY.getBytes()); //将字节转换成特定的字符串(目的是后面通过转换这些字符串成字节,进行解密) encryptString = Base64.getEncoder().encodeToString(encryptByte); } catch (Exception e) { try { throw new Exception("导出文件加密异常"); } catch (Exception e1) { e1.printStackTrace(); } } //设置excel表中的值 row.createCell(i).setCellValue(encryptString); } } try { FileOutputStream out = new FileOutputStream(absolutePath); wb.write(out); out.close(); wb.close(); flag = true; } catch (FileNotFoundException e) { JOptionPane.showMessageDialog(null, "文件打开中,不能被覆盖或保存文件!", "提示", JOptionPane.YES_OPTION); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { wb.close(); } catch (IOException e) { e.printStackTrace(); } } return flag; } *//** * 导入excel表中的数据,并将这些数据存放到一个二位数组中 * * @param filePath * 包含文件名 * @param sheetIndex * excel 表中sheet的位置 默认从0开始 * @return 带有excel表中的数据的二维数组 * @author LiangYiHuai *//* public List<ArrayList<String>> importForm(String filePath, int sheetIndex) throws Exception{ List<ArrayList<String>> list = new ArrayList<ArrayList<String>>(); Workbook wb = null; try { InputStream inp = new FileInputStream(filePath); wb = WorkbookFactory.create(inp); Sheet sheet = wb.getSheetAt(sheetIndex); int firstRowNum = sheet.getFirstRowNum();// 表格中开始有数据的行的索引 Row biginRow = sheet.getRow(firstRowNum);// 表哥中开始有数据的行 int lastRowNum = sheet.getLastRowNum();// 表格中最后一行的索引 int firstColNum = biginRow.getFirstCellNum();// 表格中开始有数据的第一列的索引 int colNum = biginRow.getLastCellNum() - firstColNum;// 表格中数据的最后一列减去第一列 if (colNum > 1) { for (int i = sheet.getFirstRowNum(); i < lastRowNum+1; i++) { ArrayList<String> tempList = new ArrayList<String>(); Row tempRow = sheet.getRow(i); for (int k = firstColNum; k < colNum; k++) { Cell tempCell = tempRow.getCell(k,Row.CREATE_NULL_AS_BLANK); *//** * switch,用来判断excel单元格中的数据是什么格式的 然后采用相应的方法来读取,否则会抛出异常 *//* switch (tempCell.getCellType()) { case Cell.CELL_TYPE_STRING: String string = tempCell.getRichStringCellValue().getString(); *//** * 解密 *//* try { this.myDecrypt(string, tempList); } catch (Exception e) { e.printStackTrace(); throw new Exception("解密异常,数据很可能被篡改"); } break; case Cell.CELL_TYPE_NUMERIC: if (DateUtil.isCellDateFormatted(tempCell)) { // 这里为日期格式化成字符串 Date date = tempCell.getDateCellValue(); String dateString = MyDateFormat.changeDateToString(date); *//** * 解密 *//* try { this.myDecrypt(dateString, tempList); } catch (Exception e) { e.printStackTrace(); throw new Exception("解密异常,数据很可能被篡改"); } } else { tempCell.setCellType(Cell.CELL_TYPE_STRING); String tempString = tempCell.getStringCellValue(); if (tempString.indexOf(".") > -1) { String doubleString = String.valueOf(new Double(tempString)); *//** * 解密 *//* try { this.myDecrypt(doubleString, tempList); } catch (Exception e) { e.printStackTrace(); throw new Exception("解密异常,数据很可能被篡改"); } } else { // tempList.add(tempString); *//** * 解密 *//* try { this.myDecrypt(tempString, tempList); } catch (Exception e) { e.printStackTrace(); throw new Exception("解密异常,数据很可能被篡改"); } } } break; case Cell.CELL_TYPE_BOOLEAN: String booleanString = String.valueOf(tempCell.getBooleanCellValue()); *//** * 解密 *//* try { this.myDecrypt(booleanString, tempList); } catch (Exception e) { e.printStackTrace(); throw new Exception("解密异常,数据很可能被篡改"); } break; case Cell.CELL_TYPE_FORMULA: tempCell.setCellType(Cell.CELL_TYPE_STRING); String tempString = tempCell.getStringCellValue(); if (tempString != null) { tempString.replaceAll("#N/A", ""); *//** * 解密 *//* try { this.myDecrypt(tempString, tempList); } catch (Exception e) { e.printStackTrace(); throw new Exception("解密异常,数据很可能被篡改"); } } break; case Cell.CELL_TYPE_ERROR: System.out.println("error"); tempList.add(""); break; case Cell.CELL_TYPE_BLANK: System.out.println("error excel cell"); throw new Exception("原始excel表本不应该出现空的单元格,所以数据很可能被人为删除"); default: System.out.println("default"); tempList.add(""); } } list.add(tempList); } } } catch (EncryptedDocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InvalidFormatException e) { e.printStackTrace(); } finally { try { wb.close(); } catch (IOException e) { e.printStackTrace(); } } return list; }3、报文摘要算法:
import java.security.MessageDigest;public class MD5Util { public final static String MD5(String s) { char hexDigits[]={'梁','不','惊','3','4','5','6','7','8','9','A','B','C','D','E','F'}; try { byte[] btInput = s.getBytes(); // 获得MD5摘要算法的 MessageDigest 对象 MessageDigest mdInst = MessageDigest.getInstance("MD5"); // 使用指定的字节更新摘要 mdInst.update(btInput); // 获得密文 byte[] md = mdInst.digest(); // 把密文转换成十六进制的字符串形式 int j = md.length; char str[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { e.printStackTrace(); return null; } } public static void main(String[] args) { System.out.println(MD5Util.MD5("Hello My name is 梁不惊")); System.out.println(MD5Util.MD5("加密")); }}
相关文章推荐
- 使用struts2框架来实现CRUD(create、read、update、delete)
- MVC、JSP实现mysql的增删改查功能的封装和简陋的界面交互
- java坦克游戏
- 贪吃蛇游戏(java)
- 考研成绩查询系统(jsp、mysql、java)
- 用java实现优先级别队列
- 用Java实现单向链表
- iOS各大牛博客
- 实用的 AIX UNIX 命令
- 在ios中解析json数据
- 关于Vmware workstation的NAT结构下的网络测试结果及分析
- 链接
- 技术揭秘12306改造(二):探讨12306两地三中心混合云架构
- Centos6.3编译安装nginx+php步骤
- Appium入门--环境准备和实例
- gdb调试libtool封装的可执行文件
- 计算文本文件中各个词(中英文)出现的频率
- java飞机游戏小项目
- 工作中遇到的问题--级联配置错误
- Web前端性能优化的14条规则