Files
qhmes/yy-admin-master/YY.Admin.Core/Util/JeecgPasswordUtil.cs

75 lines
3.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Globalization;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
namespace YY.Admin.Core.Util;
/// <summary>
/// 与 JeecgBoot <c>PasswordUtil.encrypt(username, plainPassword, salt)</c> 对齐:
/// 算法 <c>PBEWithMD5AndDES</c>,迭代 1000 次;明文为 <b>用户名 UTF-8</b>,口令为明文密码;盐为字符串转字节(与 Java 一致建议使用 UTF-8
/// </summary>
public static class JeecgPasswordUtil
{
/// <summary>与 Java PasswordUtil 中 ITERATIONCOUNT 一致</summary>
public const int IterationCount = 1000;
/// <summary>
/// 生成与 Jeecg 数据库 <c>sys_user.password</c> 一致的十六进制密文(小写)。
/// </summary>
/// <param name="username">登录账号Jeecg 的 username</param>
/// <param name="plainPassword">明文密码</param>
/// <param name="salt">Jeecg 用户表 salt 字段字符串</param>
/// <param name="saltEncoding">盐字节编码Jeecg 服务端 JVM 多为 UTF-8建议固定 UTF-8</param>
public static string Encrypt(string username, string plainPassword, string salt, Encoding? saltEncoding = null)
{
saltEncoding ??= Encoding.UTF8;
byte[] saltBytes = saltEncoding.GetBytes(salt);
byte[] plainBytes = Encoding.UTF8.GetBytes(username);
// PKCS#5 Scheme1MD5+ DES/CBC/PKCS7与 Java JCE PBEWithMD5AndDES 一致
var generator = new Pkcs5S1ParametersGenerator(new MD5Digest());
generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(plainPassword.ToCharArray()), saltBytes, IterationCount);
// 派生 DES 密钥 + IV各 64 bit
ParametersWithIV keyIv = (ParametersWithIV)generator.GenerateDerivedParameters("DES", 64, 64);
var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new DesEngine()), new Pkcs7Padding());
cipher.Init(true, keyIv);
byte[] output = new byte[cipher.GetOutputSize(plainBytes.Length)];
int len = cipher.ProcessBytes(plainBytes, 0, plainBytes.Length, output, 0);
len += cipher.DoFinal(output, len);
if (len < output.Length)
Array.Resize(ref output, len);
return BytesToHexLower(output);
}
/// <summary>
/// 校验明文密码是否与 Jeecg 存储的十六进制密文一致。
/// </summary>
public static bool Verify(string username, string plainPassword, string salt, string storedPasswordHex, Encoding? saltEncoding = null)
{
if (string.IsNullOrEmpty(storedPasswordHex))
return false;
string computed = Encrypt(username, plainPassword, salt, saltEncoding);
return string.Equals(computed, storedPasswordHex, StringComparison.OrdinalIgnoreCase);
}
private static string BytesToHexLower(byte[] src)
{
if (src == null || src.Length == 0)
return string.Empty;
var sb = new StringBuilder(src.Length * 2);
foreach (byte b in src)
sb.Append(b.ToString("x2", CultureInfo.InvariantCulture));
return sb.ToString();
}
}