加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容
概念
数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为"密文",使其只能在输入相应的密钥之后才能显示出本来内容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。
加密分类
对称加密
双方使用的同一个密钥,既可以加密又可以解密,这种加密方法称为对称加密,也称为单密钥加密
非对称加密
一对密钥由公钥和私钥组成(可以使用很多对密钥)。私钥解密公钥加密数据,公钥解密私钥加密数据(私钥公钥可以互相加密解密)。
加密算法分类
单向加密
单向加密是不可逆的,也就是只能加密,不能解密。通常用来传输类似用户名和密码,直接将加密后的数据提交到后台,因为后台不需要知道用户名和密码,可以直接将收到的加密后的数据存储到数据库
双向加密
通常分为对称性加密算法和非对称性加密算法,对于对称性加密算法,信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是对数据进行 加解密了。非对称算法与之不同,发送双方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());
}
密码正确
密码错误