java -实现php的密码加密

业务场景

最近将一个php项目在转成java项目,经过了解,原php项目使用的是Laravel 框架。php的功能使用java实现比较方便,属于你看得懂逻辑结构就写得出代码那种。随着前端越来越面向对象,php和java都只需要处理业务逻辑对外提供接口数据便可。而今天要和大家分享的是,使用Laravel框架中的推荐加密算法后如何用java实现。

Laravel中推荐的密码加密算法

在项目中使用的是laravel的Hash::make,底层的实现 image以此可以看出是使用PHP的password_hash()实现的。这个方法有不同的是实现方式,在项目的是采用的默认实现,

string password_hash ( string $password , integer $algo [, array $options ])

它有三个参数:密码、哈希算法、选项。前两项为必须的。 让我们使用password_hash()简单的创建一个哈希密码: 复制代码 代码如下:

$pwd = "123456";
$hash = password_hash($pwd, PASSWORD_DEFAULT);
echo $hash;

上例输出结果类似:

$2y$10$4kAu4FNGuolmRmSSHgKEMe3DbG5pm3diikFkiAKNh.Sf1tPbB4uo2

并且刷新页面该哈希值也会不断的变化。

这里便有了一个疑问,同样的值同意的算法不同的值如何验证如何实现。 上述的方法支持三种算法

  • PASSWORD_DEFAULT - 使用 bcrypt 算法 (PHP 5.5.0 默认)。 注意,该常量会随着 PHP 加入更新更高强度的算法而改变。 所以,使用此常量生成结果的长度将在未来有变化。 因此,数据库里储存结果的列可超过60个字符(最好是255个字符)。
  • PASSWORD_BCRYPT - 使用 CRYPT_BLOWFISH 算法创建散列。 这会产生兼容使用 "$2y$" 的 crypt()。 结果将会是 60 个字符的字符串, 或者在失败时返回 FALSE。
  • PASSWORD_ARGON2I - 使用 Argon2 散列算法创建散列。

PASSWORD_BCRYPT 支持的选项:

  • salt(string) - 手动提供散列密码的盐值(salt)。这将避免自动生成盐值(salt)。 省略此值后,password_hash() 会为每个密码散列自动生成随机的盐值。这种操作是有意的模式
  • 盐值(salt)选项从 PHP 7.0.0 开始被废弃(deprecated)了。 现在最好选择简单的使用默认产生的盐值。
  • cost (integer) - 代表算法使用的 cost。crypt() 页面上有 cost 值的例子。 省略时,默认值是 10。 这个 cost 是个不错的底线,但也许可以根据自己硬件的情况,加大这个值。

我要处理的密码是 因为 password_hash 使用的是 crypt 算法, 因此参与计算 hash值的:

算法(就像身份证开头能知道省份一样, 由盐值的格式决定), cost(默认10) 和 盐值 是在$hash中可以直接看出来的!

所以说, Laravel 中bcrypt的盐值是PHP自动随机生成的字符, 虽然同一个密码每次计算的hash不一样.

但是通过 $hash 和 密码, 却可以验证密码的正确性!

具体来说, 比如这个

$hash = password_hash('password',PASSWORD_BCRYPT,['cost' => 10]);
echo $hash;
// 比如我这次算的是
// $hash = '$2y$10$DyAJOutGjURG9xyKgAaCtOm4K1yezvgNkxHf6PhuLYBCENk61bePm';

那么我们从这个 crypt的hash值中可以看到, 因为以$2y$开头, 所以它的算法是 CRYPT_BLOWFISH .

同时 CRYPT_BLOWFISH 算法盐值格式规定是 :

以$2y$开头 + 一个两位cost参数 + $ + 22位随机字符("./0-9A-Za-z")

$hash(CRYPT_BLOWFISH是固定60位) = 盐值 + 31位单向加密后的值
参见: https://secure.php.net/manual/en/function.crypt.php

验证密码

if (password_verify('password', $hash)) {
    echo '密码正确.';
} else {
    echo '密码错误!';
}

// 原理是: 

if ($hash === crypt('password', '$2y$10$DyAJOutGjURG9xyKgAaCtO')) {
    echo '密码正确.';
} else {
    echo '密码错误!';
}

实现

在http://stackoverflow.com/questions/3292160/equivalent-of-phps-crypt-function-in-java中有人提到了apache的commons-codes里面的两个类UnixCript 和Md5Crypt

参考链接

http://shidan66.iteye.com/blog/1974285

http://php.net/manual/zh/function.password-hash.php

https://segmentfault.com/q/1010000004466485

http://www.php.net/manual/zh/function.password-hash.php

https://segmentfault.com/q/1010000011719668

https://blog.csdn.net/zhanghao143lina/article/details/77662547

原文链接:加载失败,请重新获取