我正在尝试在Liferay使用PBKDF2WithHmacSHA1 / 160/128000的c#中编写相同的算法,因为我们已经将哈希密码迁移到不同的平台。但是,散列密码值在C#中会有所不同 不太确定我做错了什么。我对Java不是很熟悉。
在Java中传递的参数是
String algorithm = "PBKDF2WithHmacSHA1/160/128000"
String plainTextPassword = "!!Fres1966"
String encryptedPassword = null
Java中的哈希值=“AAAAoAAB9ACnaq7ogwbkgRWfNcsfFh2DEMKmfl7JAqR8SAqk” c#中的哈希值=“FAAAAAD0AQAAAAAAAAAAAFJZUX3EUFdhFHeMZLSdlo9RxsxO”
有一行我无法复制的代码是
BigEndianCodec.putLong(_saltBytes, 0, SecureRandomUtil.nextLong())
不太确定这行代码在做什么以及如何在c#
中复制类似的逻辑Java中的代码-------------
public class PBKDF2PasswordEncryptor
extends BasePasswordEncryptor implements PasswordEncryptor {
@Override
public String[] getSupportedAlgorithmTypes() {
return new String[] {PasswordEncryptorUtil.TYPE_PBKDF2};
}
@Override
protected String doEncrypt(
String algorithm, String plainTextPassword,
String encryptedPassword)
throws PwdEncryptorException {
try {
PBKDF2EncryptionConfiguration pbkdf2EncryptionConfiguration =
new PBKDF2EncryptionConfiguration();
pbkdf2EncryptionConfiguration.configure(
algorithm, encryptedPassword);
byte[] saltBytes = pbkdf2EncryptionConfiguration.getSaltBytes();
PBEKeySpec pbeKeySpec = new PBEKeySpec(
plainTextPassword.toCharArray(), saltBytes,
pbkdf2EncryptionConfiguration.getRounds(),
pbkdf2EncryptionConfiguration.getKeySize());
String algorithmName = algorithm;
int index = algorithm.indexOf(CharPool.SLASH);
if (index > -1) {
algorithmName = algorithm.substring(0, index);
}
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(
algorithmName);
SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);
byte[] secretKeyBytes = secretKey.getEncoded();
ByteBuffer byteBuffer = ByteBuffer.allocate(
2 * 4 + saltBytes.length + secretKeyBytes.length);
byteBuffer.putInt(pbkdf2EncryptionConfiguration.getKeySize());
byteBuffer.putInt(pbkdf2EncryptionConfiguration.getRounds());
byteBuffer.put(saltBytes);
byteBuffer.put(secretKeyBytes);
return Base64.encode(byteBuffer.array());
}
catch (Exception e) {
throw new PwdEncryptorException(e.getMessage(), e);
}
}
private static final int _KEY_SIZE = 160;
private static final int _ROUNDS = 128000;
private static final int _SALT_BYTES_LENGTH = 8;
private static Pattern _pattern = Pattern.compile(
"^.*/?([0-9]+)?/([0-9]+)$");
private class PBKDF2EncryptionConfiguration {
public void configure(String algorithm, String encryptedPassword)
throws PwdEncryptorException {
if (Validator.isNull(encryptedPassword)) {
Matcher matcher = _pattern.matcher(algorithm);
if (matcher.matches()) {
_keySize = GetterUtil.getInteger(
matcher.group(1), _KEY_SIZE);
_rounds = GetterUtil.getInteger(matcher.group(2), _ROUNDS);
}
BigEndianCodec.putLong(
_saltBytes, 0, SecureRandomUtil.nextLong());
}
else {
byte[] bytes = new byte[16];
try {
byte[] encryptedPasswordBytes = Base64.decode(
encryptedPassword);
System.arraycopy(
encryptedPasswordBytes, 0, bytes, 0, bytes.length);
}
catch (Exception e) {
throw new PwdEncryptorException(
"Unable to extract salt from encrypted password " +
e.getMessage(),
e);
}
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
_keySize = byteBuffer.getInt();
_rounds = byteBuffer.getInt();
byteBuffer.get(_saltBytes);
}
}
public int getKeySize() {
return _keySize;
}
public int getRounds() {
return _rounds;
}
public byte[] getSaltBytes() {
return _saltBytes;
}
private int _keySize = _KEY_SIZE;
private int _rounds = _ROUNDS;
private byte[] _saltBytes = new byte[_SALT_BYTES_LENGTH];
}
}
public string HasPassword(string password)
{
byte[] salt = new byte[8];
Rfc2898DeriveBytes Rfcbytes = new Rfc2898DeriveBytes(password, salt,
128000);
byte[] key = Rfcbytes.GetBytes(160/8);
var ms = new MemoryStream(8+salt.Length+key.Length);
using (BinaryWriter writer = new BinaryWriter(ms))
{
writer.Write(160/8);
writer.Write(128000);
writer.Write(salt);
writer.Write(key);
}
byte[] bytes = ms.ToArray();
string finalhash = Convert.ToBase64String(bytes);
return finalhash;
}
答案 0 :(得分:0)
Category: {
Id: Integer,
Name: String
}
SubCategory: {
Id: Integer,
Name: String,
CategoryId: Integer
}
似乎是"生成一个随机的8字节值并将其写入数组(以Big Endian顺序;但它是随机的,所以这并不重要)"
所以你想要
BigEndianCodec.putLong(_saltBytes, 0, SecureRandomUtil.nextLong())
在分配using (RandomNumberGenerator csprng = RandomNumberGenerator.Create())
{
csprng.GetBytes(salt);
}
并将其传递给salt
'之间构造函数。