您的位置:首页 > 其它

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("加密"));    }}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: