《干货转载》用户密码加密策略之BCryptPasswordEncoder

http://www.cnblogs.com/hujunzheng/p/6478003.html

https://www.cnblogs.com/joylee/p/9674260.html

BCryptPasswordEncoder 

spring security中的BCryptPasswordEncoder方法采用SHA-256 +随机盐+密钥对密码进行加密。SHA系列是Hash算法,其过程是不可逆的。

(1)加密(encode):注册用户时,使用SHA-256+随机盐+密钥把用户输入的密码进行hash处理,得到密码的hash值。

//BCryptPasswordEncoder.java	

public BCryptPasswordEncoder(int strength, SecureRandom random) {
		if (strength != -1 && (strength < BCrypt.MIN_LOG_ROUNDS || strength > BCrypt.MAX_LOG_ROUNDS)) {
			throw new IllegalArgumentException("Bad strength");
		}
		this.strength = strength;
		this.random = random;
	}

	public String encode(CharSequence rawPassword) {
		String salt;
		if (strength > 0) {
			if (random != null) {
				salt = BCrypt.gensalt(strength, random);
			}
			else {
				salt = BCrypt.gensalt(strength);
			}
		}
		else {
			salt = BCrypt.gensalt();
		}
		return BCrypt.hashpw(rawPassword.toString(), salt);
	}

(2)密码匹配(matches):用户登录时,密码匹配阶段并没有进行密码解密,而是使用相同的算法把的密码进行加密处理,得到密码的hash值,然后将其与从数据库中查询到的密码hash值进行比较。如果两者相同,说明用户输入的密码正确。

//BCryptPasswordEncoder.java		
public boolean matches(CharSequence rawPassword, String encodedPassword) {
		if (encodedPassword == null || encodedPassword.length() == 0) {
			logger.warn("Empty encoded password");
			return false;
		}

		if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
			logger.warn("Encoded password does not look like BCrypt");
			return false;
		}

		return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
	}
	
//BCrypt.java
public static boolean checkpw(String plaintext, String hashed) {
		return equalsNoEarlyReturn(hashed, hashpw(plaintext, hashed));
	}
	//BCrypt.java


    /**
	 * Hash a password using the OpenBSD bcrypt scheme
	 * @param password the password to hash
	 * @param salt the salt to hash with (perhaps generated using BCrypt.gensalt)
	 * @return the hashed password
	 * @throws IllegalArgumentException if invalid salt is passed
	 */
	public static String hashpw(String password, String salt) throws IllegalArgumentException {
		BCrypt B;
		String real_salt;
		byte passwordb[], saltb[], hashed[];
		char minor = (char) 0;
		int rounds, off = 0;
		StringBuilder rs = new StringBuilder();

		if (salt == null) {
			throw new IllegalArgumentException("salt cannot be null");
		}

		int saltLength = salt.length();

		if (saltLength < 28) {
			throw new IllegalArgumentException("Invalid salt");
		}

		if (salt.charAt(0) != '$' || salt.charAt(1) != '2') {
			throw new IllegalArgumentException("Invalid salt version");
		}
		if (salt.charAt(2) == '$') {
			off = 3;
		}
		else {
			minor = salt.charAt(2);
			if (minor != 'a' || salt.charAt(3) != '$') {
				throw new IllegalArgumentException("Invalid salt revision");
			}
			off = 4;
		}

		if (saltLength - off < 25) {
			throw new IllegalArgumentException("Invalid salt");
		}

		// Extract number of rounds
		if (salt.charAt(off + 2) > '$') {
			throw new IllegalArgumentException("Missing salt rounds");
		}
		rounds = Integer.parseInt(salt.substring(off, off + 2));

		real_salt = salt.substring(off + 3, off + 25);
		try {
			passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8");
		}
		catch (UnsupportedEncodingException uee) {
			throw new AssertionError("UTF-8 is not supported");
		}

		saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);

		B = new BCrypt();
		hashed = B.crypt_raw(passwordb, saltb, rounds);

		rs.append("$2");
		if (minor >= 'a') {
			rs.append(minor);
		}
		rs.append("$");
		if (rounds < 10) {
			rs.append("0");
		}
		rs.append(rounds);
		rs.append("$");
		encode_base64(saltb, saltb.length, rs);
		encode_base64(hashed, bf_crypt_ciphertext.length * 4 - 1, rs);
		return rs.toString();
	}

这种算法的特点就是: 同一个密码每次加密的结果不一样, 但是通过match方法能匹配上.

前端BCrypt加密js

https://github.com/nevins-b/javascript-bcrypt

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值