MessageDigest類
MessageDigest 類是一個引擎類,它是爲了提供諸如 SHA1 或 MD5 等密碼上安全的報文摘要功能而設計的。密碼上安全的報文摘要可接受任意大小的輸入(一個字節數組),併產生固定大小的輸出,該輸出稱爲一個摘要或散列。
創建MessageDigest對象
計算信息摘(即散列碼)要做的第一步是創建 MessageDigest對象 實例。像所有的引擎類一樣,獲取某類報文摘要算法(即散列算法,比如MD5)的 MessageDigest 對象的途徑是調用 MessageDigest 類中的 getInstance 靜態 factory 方法:
public static MessageDigest getInstance(String algorithm)
注意1:即時給定MessageDigest的實現是不可複製的,則仍然能夠通過getInstance方法實例化幾個實例計算來同時進行摘要信息的計算。
注意2:由於歷史原因,此類是抽象的,是從 MessageDigestSpi
擴展的。應用程序開發人員只應該注意在此 MessageDigest
類中定義的方法;超類中的所有方法是供希望提供自己的信息摘要算法實現的加密服務提供者使用的。
注意3:MessageDigest並不是單實例的。如下代碼所示:
try
{
MessageDigest mdTemp1 = MessageDigest.getInstance("MD5");
MessageDigest mdTemp2= MessageDigest.getInstance("MD5");
MessageDigest mdTemp3= MessageDigest.getInstance("MD5");
System.out.println("mdTemp1==mdTemp2?:"+(mdTemp1==mdTemp2));
System.out.println("mdTemp2==mdTemp3?:"+(mdTemp2==mdTemp3));
} catch (NoSuchAlgorithmException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
運行結果
mdTemp1==mdTemp2?:false
mdTemp2==mdTemp3?:false
注意:算法名不區分大小寫。例如,以下所有調用都是相等的:
MessageDigest.getInstance("SHA");
MessageDigest.getInstance("sha");
MessageDigest.getInstance("sHa");
方法摘要
方法摘要 | |
---|---|
Object |
clone() 如果實現是可複製的,則返回一個副本。 |
byte[] |
digest() 通過執行諸如填充之類的最終操作完成哈希計算。 |
byte[] |
digest(byte[] input) 使用指定的字節數組對摘要進行最後更新,然後完成摘要計算。 |
int |
digest(byte[] buf, int offset, int len) 通過執行諸如填充之類的最終操作完成哈希計算。 |
String |
getAlgorithm() 返回標識算法的獨立於實現細節的字符串。 |
int |
getDigestLength() 返回以字節爲單位的摘要長度,如果提供程序不支持此操作並且實現是不可複製的,則返回 0。 |
static MessageDigest |
getInstance(String algorithm) 生成實現指定摘要算法的 MessageDigest 對象。 |
static MessageDigest |
getInstance(String algorithm, Provider provider) 生成實現指定提供程序提供的指定算法的 MessageDigest 對象,如果該算法可從指定的提供程序得到的話。 |
static MessageDigest |
getInstance(String algorithm, String provider) 生成實現指定提供程序提供的指定算法的 MessageDigest 對象,如果該算法可從指定的提供程序得到的話。 |
Provider |
getProvider() 返回此信息摘要對象的提供程序。 |
static boolean |
isEqual(byte[] digesta, byte[] digestb) 比較兩個摘要的相等性。 |
void |
reset() 重置摘要以供再次使用。 |
String |
toString() 返回此信息摘要對象的字符串表示形式。 |
void |
update(byte input) 使用指定的字節更新摘要。 |
void |
update(byte[] input) 使用指定的字節數組更新摘要。 |
void |
update(byte[] input, int offset, int len) 使用指定的字節數組,從指定的偏移量開始更新摘要。 |
void |
update(ByteBuffer input) 使用指定的 ByteBuffer 更新摘要。 |
例子演示
public static void main(String[] args) throws NoSuchAlgorithmException {
MessageDigest instance = MessageDigest.getInstance("md5");
String UUID = java.util.UUID.randomUUID().toString();
String pwd = "123456";
String name = UUID+pwd;
System.out.println("鹽值:"+UUID);
System.out.println("密碼:"+pwd);
System.out.println("鹽值加密:"+name);
instance.update(name.getBytes());
instance.reset();
byte[] digest = instance.digest(name.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
String row = Integer.toHexString(b&0xff);
if(row.length()==1){
row = "0" + row;
}
sb.append(row);
}
System.out.println("加密後:"+sb.toString());
}
文件摘要加密
public void insertAttachement(String title, MultipartFile mFile) {
if(title==null||title.trim().length()==0){
throw new ServiceException("標題不能爲空");
}
if(mFile==null){
throw new ServiceException("不允許上傳空文件");
}
byte[] bytes ;
String digests= null;
try {
//將文件摘要轉爲字節
bytes = mFile.getBytes();
//將摘要後的字節數組進行MD5加密
digests = DigestUtils.md5DigestAsHex(bytes);
} catch (Exception e) {
e.printStackTrace();
throw new ServiceException("文件上傳失敗");
}
Integer rows = attachementsDao.getRowCountByDigest(digests);
if(rows>0){
throw new ServiceException("文件已上傳,請勿重複上傳!");
}
String fileName = mFile.getOriginalFilename();
String contentType = mFile.getContentType();
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
String timeDate = sd.format(new Date());
String path = "F:"+File.separator+"upload"+File.separator+timeDate;
File file = new File(path);
//文件夾是否存在 不存在將創建
if(!file.exists()){
file.mkdirs();
}
File filepath = new File(path,fileName);
try {
mFile.transferTo(filepath);
} catch (IOException e) {
e.printStackTrace();
throw new ServiceException("文件上傳失敗");
}
Attachements att = new Attachements();
att.setTitle(title);
att.setFileName(fileName);
att.setFilePath(filepath.getAbsolutePath());
att.setFileDisgest(digests);
att.setContentType(contentType);
Integer row = attachementsDao.insertAttachement(att);
if(row<1){
throw new ServiceException("新增失敗");
}
}
運行結果
鹽值:c971db77-f109-401a-95f7-49b0f2bf0863
密碼:123456
鹽值加密:c971db77-f109-401a-95f7-49b0f2bf0863123456
加密後:525f7296b1ca744ca751344a4196ad17