JAVA中进行数据完整性验证
最近在看JAVA安全方面的东东。简单地说,安全包括访问控制、数据安全两部分。安全访问控制是根据系统需求进行设计的,对资源进行访问控制的一种措
施。而数据安全包括数据传输过程中的安全防范措施,包括数据完整性、传输安全性、接收/发送方不可否认性等方面。下面就数据完整性验证部分做简单的
介绍。
假如我要下载一个最新版本的tomcat7 ,我会访问http://tomcat.apache.org/download-70.cgi。在下载列表中,我可以点击链接进行下载。但如何保证在
下载过程中,没有被其他程序篡改过?其他程序可能是网络传输过程中的第三方监听者,也有可能是我本地环境中存在的不良程序,如木马。在apache的下
载列表旁边,我们会发现有个md5的链接,点击打开之后,会出现如下字符串:cbad484f0b02f0daf775137aee0f4e2e *apache-tomcat-7.0.21.zip。这是做什
么用的呢?
这是一十六进制的编码字符串,又称“数字指纹”。他其实就是对原版文件(发送方发送的文件)完整性的验证标识符。当我们把文件下载到本地后,可以
自己对其进行验证,若验证的结果与发送方提供的指纹一致的话,则表明,在传输过程中,数据文件没有被篡改或其他损耗。
在JAVA中,我们可以借助JDK自带的包或者第三方安全工具包对其进行完整性验证工作。这里使用了BouncyCastle 工具包,下载地址为: http://www.bouncycastle.org/download/bcprov-jdk16-146.jar
代码如下:
public static void testInputStream(String filePath){
/**
* 使用BouncyCastleProvider,需加载对应的包。
*/
Security.addProvider(new BouncyCastleProvider());
Provider provider = Security.getProvider("BC");
try {
/**
* 使用MD5进行完整性校验
*/
MessageDigest digest = MessageDigest.getInstance("MD5",provider);
/**
* 获取文件流
*/
FileInputStream in=new FileInputStream(filePath);
DigestInputStream din =new DigestInputStream(in,digest);
int bfSize=40000000;
int length=in.available();
int currentSize=0;
boolean goon=true;
/**
* 根据文件流更新摘要数据源
*/
while(goon){
byte[] buffer =new byte[bfSize];
int readSize=bfSize;
if((length-currentSize)<bfSize){
goon=false;
readSize=length-currentSize;
}else{
goon=true;
readSize=bfSize;
}
din.read(buffer, 0, readSize);
if(goon==false){
currentSize +=readSize;
}else{
currentSize+=bfSize;
}
}
/**
* 生成摘要信息
*/
byte[] output = digest.digest();
/**
* 生成十六进制字符串
*/
String outputStr =new String(Hex.encode(output));
System.out.println("filePath:"+filePath);
System.out.println("MD5:"+outputStr);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args){
String filePath="E:/软件/os/apache-tomcat-7.0.21.zip";
testInputStream(filePath);
}