Java

TOTP 算法校验一则

TOTP算法(Time-based One-time Password algorithm)是一种从共享密钥和当前时间计算一次性密码的算法; 它已被采纳为Internet工程任务组标准RFC 6238, 是Initiative for Open Authentication(OATH)的基石, 并被用于许多双因素身份验证系统;

pom.xml

<dependency>
    <groupId>de.taimos</groupId>
    <artifactId>totp</artifactId>
    <version>1.0</version>
</dependency>

java

public static void main(String[] args) {
    //1. 随机key 
    byte[] keybt =  "QDWSM3OYBDGHLAJJJHGJVDM3CSNCWHVK".getBytes();
    String encode = Base32.encode(keybt);
    //2. 编码为base32 (给客户端, 例Google Authenticator作为key的)
    System.out.println(encode );
    byte[] keybt32 =  Base32.decode(encode);
    //3. 需编码为十六进制字符串
    String secretKey = HexUtil.encodeHexStr(keybt32 );
    String lastCode = null;
    while (true) {
        //4. 获取代码(每隔30s刷新一次)
        String code =  TOTP.getOTP(secretKey);
        if (!code.equals(lastCode)) {
            System.out.println(code);
        }
        lastCode = code;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {break;};
    }
}

生成Google Authenticator 二维码

public static String getGoogleAuthenticatorBarCode(String secretKey, 
												   String account, String issuer) {
    try {
        return "otpauth://totp/"
                + URLEncoder.encode(issuer + ":" + account, "UTF-8").replace("+", "%20")
                + "?secret=" + URLEncoder.encode(secretKey, "UTF-8").replace("+", "%20")
                + "&issuer=" + URLEncoder.encode(issuer, "UTF-8").replace("+", "%20");
    } catch (UnsupportedEncodingException e) {
        throw new IllegalStateException(e);
    }
}

otpauth://totp/[客户端显示的账户信息]?secret=[secretBase32]

PBKDF2 算法校验一则

  /**
     * 
     * @param password 密码
     * @param salt
     * @param iterations 迭代次数
     * @return
     * @auth yangfh
     */
public static String generateStorngPasswordHash(String password, long salt, int iterations) {
		try {
			char[] chars = password.toCharArray();
			byte[] salt_ = longToBytes(salt);
			PBEKeySpec spec = new PBEKeySpec(chars, salt_, iterations, 64 * 8);
			SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
			byte[] hash = skf.generateSecret(spec).getEncoded();
			return iterations + ":" + toHex(salt_) + ":" + toHex(hash);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
    /**
     * 校验 
     * originalPassword 密码
     * storedPassword PasswordHash 
     */
	public static boolean validatePassword(String originalPassword, String storedPassword) {
		try {
			String[] parts = storedPassword.split(":");
			int iterations = Integer.parseInt(parts[0]);
 
			byte[] salt = fromHex(parts[1]);
			byte[] hash = fromHex(parts[2]);
 
			PBEKeySpec spec = new PBEKeySpec(originalPassword.toCharArray(), salt, iterations, hash.length * 8);
			SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
			byte[] testHash = skf.generateSecret(spec).getEncoded();
 
			int diff = hash.length ^ testHash.length;
			for (int i = 0; i < hash.length && i < testHash.length; i++) {
				diff |= hash[i] ^ testHash[i];
			}
			return diff == 0;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	public static byte[] longToBytes(long value) {
		byte[] src = new byte[8];
		src[0] = (byte) (value & 0xFF);
		src[1] = (byte) ((value >> 8) & 0xFF);
		src[2] = (byte) ((value >> 16) & 0xFF);
		src[3] = (byte) ((value >> 24) & 0xFF);
		src[4] = (byte) ((value >> 32) & 0xFF);
		src[5] = (byte) ((value >> 40) & 0xFF);
		src[6] = (byte) ((value >> 48) & 0xFF);
		src[7] = (byte) ((value >> 56) & 0xFF);
		return src;
	}
	public static byte[] fromHex(String hex) throws NoSuchAlgorithmException {
		byte[] bytes = new byte[hex.length() / 2];
		for (int i = 0; i < bytes.length; i++) {
			bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
		}
		return bytes;
	}
	public static String toHex(byte[] array) throws NoSuchAlgorithmException {
		BigInteger bi = new BigInteger(1, array);
		String hex = bi.toString(16);
 
		int paddingLength = (array.length * 2) - hex.length();
		if (paddingLength > 0) {
			return String.format("%0" + paddingLength + "d", 0) + hex;
		} else {
			return hex;
		}
	}
String enpwd = EncryptionUtils.generateStorngPasswordHash(dto.getSystemUserPwd(), System.currentTimeMillis(),1000);