1、密碼為什么要加密
存在數據庫中的密碼如果是明文,一旦數據庫數據泄漏了,別人就可以拿着你的賬號密碼為所欲為。更何況有很多人在各個平台的用戶名密碼都是一致的。所以用戶的密碼,一定要加密存儲。
2、加密算法的種類
2.1、對稱加密,指的是需要對加密和解密使用相同密鑰的加密算法。常見的對稱加密算法有:DES、3DES、AES等。
2.2、非對稱加密,它需要兩個密鑰,一個稱為公鑰(public key),一個稱為私鑰(private key)。加密和解密使用兩個不同的密鑰。例如:甲生成一對密鑰,並將其中的一把作為公鑰向其他人公開,得到該公鑰的乙使用該密鑰對信息進行加密后在發送給甲,甲使用自己保存的另一把私鑰,對加密后的信息進行解密。常見的非對稱加密算法有RSA、DSA等。
2.3、單向hash算法,就是把任意長的消息串轉化為固定長度的輸出串的一種算法。一般用戶信息摘要。常見的有MD5、SHA、MAC等。
2.4、加鹽hash算法,鹽(Salt),在密碼學中,是指在散列之前將散列內容(例如:密碼)的任意固定位置插入特定的字符串。這個在散列中加入字符串的方式稱為“加鹽”。其作用是讓加鹽后的散列結果和沒有加鹽的結果不相同,在不同的應用情景中,這個處理可以增加額外的安全性。
3、密碼加密的算法選擇
3.1、可逆的算法不要選,會增加密碼泄漏的風險。
3.2、MD5不要選,MD5並不是一個加密算法,而是一個信息摘要算法,可通過彩虹表進行破解,且相同明文加密后的密文是一致的,一旦破解出來一個,其余相同的也都知道了。
3.3、不要加固定的鹽,比如說用戶名,郵箱等,如果數據庫被攻破了,鹽會被拿到。一旦鹽泄漏,根據鹽重新建立彩虹表可以進行破解。
所以用於密碼加密的算法最好是,不可逆的,且使用隨機鹽,常用做密碼加密的算法有bcrypt、scrypt。
4、使用bcrypt對密碼進行加密(推薦使用)
4.1、導入依賴
<dependency> <groupId>org.mindrot</groupId> <artifactId>jbcrypt</artifactId> <version>0.4</version> </dependency>
4.2、對密碼進行加密
@Override @Transactional(rollbackFor = Exception.class) public UserDTO create(UserDTO userDTO) { /* * 將密碼加密成密文 */ userDTO.setPassword(BCrypt.hashpw(userDTO.getPassword(),BCrypt.gensalt())); UserDO userDO = new UserDO(); BeanUtils.copyProperties(userDTO, userDO); userRepository.save(userDO); userDTO.setId(userDO.getId()); return userDTO; }
4.3、認證過濾器,修改密碼校驗方式
4.4、創建兩個用戶,並使用相同的密碼123456,查看數據庫中存儲的密碼是不一致的
4.5、測試認證功能
這樣,我們數據庫中的密碼就安全多了。
5、使用scrypt對密碼進行加密
5.1、導入依賴
<dependency> <groupId>com.lambdaworks</groupId> <artifactId>scrypt</artifactId> <version>1.4.0</version> </dependency>
5.2、對密碼進行加密
userDTO.setPassword(SCryptUtil.scrypt(userDTO.getPassword(),2 << 14,8,1));
5.3、認證過濾器,修改密碼校驗方式
效果與使用bcrypt類似,該算法唯一的缺點就是慢。
源碼地址:https://github.com/caofanqi/study-security/tree/dev-encryption