加密,是以某種特殊的算法改變原有的信息數據,使得未授權的用戶即使獲得了已加密的信息,但因不知解密的方法,仍然無法瞭解信息的內容
概念
數據加密的基本過程就是對原來爲明文的文件或數據按某種算法進行處理,使其成爲不可讀的一段代碼,通常稱爲"密文",使其只能在輸入相應的密鑰之後才能顯示出本來內容,通過這樣的途徑來達到保護數據不被非法人竊取、閱讀的目的。該過程的逆過程爲解密,即將該編碼信息轉化爲其原來數據的過程。
加密分類
對稱加密
雙方使用的同一個密鑰,既可以加密又可以解密,這種加密方法稱爲對稱加密,也稱爲單密鑰加密
非對稱加密
一對密鑰由公鑰和私鑰組成(可以使用很多對密鑰)。私鑰解密公鑰加密數據,公鑰解密私鑰加密數據(私鑰公鑰可以互相加密解密)。
加密算法分類
單向加密
單向加密是不可逆的,也就是隻能加密,不能解密。通常用來傳輸類似用戶名和密碼,直接將加密後的數據提交到後臺,因爲後臺不需要知道用戶名和密碼,可以直接將收到的加密後的數據存儲到數據庫
雙向加密
通常分爲對稱性加密算法和非對稱性加密算法,對於對稱性加密算法,信息接收雙方都需事先知道密匙和加解密算法且其密匙是相同的,之後便是對數據進行 加解密了。非對稱算法與之不同,發送雙方A,B事先均生成一堆密匙,然後A將自己的公有密匙發送給B,B將自己的公有密匙發送給A,如果A要給B發送消 息,則先需要用B的公有密匙進行消息加密,然後發送給B端,此時B端再用自己的私有密匙進行消息解密,B向A發送消息時爲同樣的道理。
常見算法
算法 | 描述 |
DES(Data Encryption Standard) | 數據加密標準,速度較快,適用於加密大量數據的場合; |
3DES(Triple DES) | 是基於DES,對一塊數據用三個不同的密鑰進行三次加密,強度更高; |
RC2和 RC4 | 用變長密鑰對大量數據進行加密,比 DES 快; |
IDEA(International Data Encryption Algorithm) | 國際數據加密算法:使用 128 位密鑰提供非常強的安全性; |
RSA | 由 RSA 公司發明,是一個支持變長密鑰的公共密鑰算法,需要加密的文件塊的長度也是可變的; |
DSA(Digital Signature Algorithm) | 數字簽名算法,是一種標準的 DSS(數字簽名標準); |
AES(Advanced Encryption Standard) | 高級加密標準,是下一代的加密算法標準,速度快,安全級別高,目前 AES 標準的一個實現是 Rijndael 算法; |
BLOWFISH | 它使用變長的密鑰,長度可達448位,運行速度很快; |
MD5 (Message-Digest Algorithm) | 消息摘要算法,一種被廣泛使用的密碼散列函數,可以產生出一個128位(16字節)的散列值(hash value),用於確保信息傳輸完整一致 |
MD5加密的使用
public static void main(String[] args) {
//用戶密碼
String pwd = "123456";
//鹽值
String salt = "copy";
// 第一個參數爲加密方式,第二個參數爲需要加密的密碼,第三個參數爲加密添加的鹽值,第四個參數爲加密的次數
SimpleHash si = new SimpleHash("MD5",pwd,salt,2);
System.out.println("加密後的密碼爲:"+si.toString());
}
輸出的結果
加密後的密碼爲:acd1b8d62a8369c3d6278ea6f663407b
鹽值的作用
使用MD5存在一個問題,相同的password生成的hash值是相同的,如果兩個用戶設置了相同的密碼,那麼數據庫中會存儲兩個相同的值,這是極不安全的,加Salt可以在一定程度上解決這一問題,所謂的加Salt方法,就是加點‘佐料’。其基本想法是這樣的,當用戶首次提供密碼時(通常是註冊時)由系統自動往這個密碼裏撒一些‘佐料’,然後在散列,而當用戶登錄時,系統爲用戶提供的代碼上撒上相同的‘佐料’,然後散列,再比較散列值,來確定密碼是否正確。
加鹽的原理:
給原文加入隨機數生成新的MD5的值
shiro中使用MD5加密
認證方法中修改
public class ShiroRealmsOne extends AuthorizingRealm{
/**
* 認證
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username =(String)token.getPrincipal();
if(!"admin".equals(username)){
return null;
}
//String pwd = "123456"; 密碼
//String salt = "copy"; 鹽值
// acd1b8d62a8369c3d6278ea6f663407b 兩次迭代加密後的密碼
String salt = "copy";
ByteSource saltByte = ByteSource.Util.bytes(salt);
String password = "acd1b8d62a8369c3d6278ea6f663407b";
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,password,saltByte,this.getName());
return info;
}
/**
* 授權
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO 自動生成的方法存根
return null;
}
}
shiro-realms-md5.ini文件
[main]
#定義憑證匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=MD5
#散列迭代次數
credentialsMatcher.hashIterations=2
#需要將憑證匹配器設置到realm
shiroUserRealm=com.sumeng.shiro.ShiroRealmsOne
shiroUserRealm.credentialsMatcher=$credentialsMatcher
securityManager.realms=$shiroUserRealm
測試
@Test
public void demoTwo(){
// 裝入 INI 配置
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realms-md5.ini");
//創建SecurityManager對象
SecurityManager instance = factory.getInstance();
//使SecurityManager可以訪問
SecurityUtils.setSecurityManager(instance);
//接受提交的用戶名和密碼:
UsernamePasswordToken tooken = new UsernamePasswordToken("admin","123456");
//獲取當前主體
Subject subject = SecurityUtils.getSubject();
try {
subject.login(tooken);
} catch (UnknownAccountException e) {
System.out.println("用戶名錯誤!");
}
catch (IncorrectCredentialsException e) {
System.out.println("密碼錯誤!");
}
System.out.println("是否認證成功:" + subject.isAuthenticated());
}
密碼正確
密碼錯誤