中的Liferay加密算法实现

中的Liferay加密算法实现

本文介绍了.Net C#中的Liferay加密算法实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于我们将哈希密码迁移到了不同​​的平台,因此我试图在Liferay使用PBKDF2WithHmacSHA1/160/128000的c#中编写相同的算法.但是,哈希密码值在C#中却有所不同不太确定我在哪里做错了.我对Java不太熟悉.

I am trying to write the same algorithm in c# of what Liferay uses PBKDF2WithHmacSHA1/160/128000 as we have hashed passwords migrated to different platforms. however the hashed passwords values are coming as different in C#Not too sure where I am doing wrong. I am not very much familiar with Java.

在Java中传递的参数是

parameters passed in Java are

String algorithm = "PBKDF2WithHmacSHA1/160/128000"
String plainTextPassword = "!!Fres1966"
String encryptedPassword = null

Java中的

哈希值="AAAAoAAB9ACnaq7ogwbkgRWfNcsfFh2DEMKmfl7JAqR8SAqk"c#中的哈希值="FAAAAAD0AQAAAAAAAAAAAFJZUX3EUFdhFHeMZLSdlo9RxsxO"

hash value in Java = "AAAAoAAB9ACnaq7ogwbkgRWfNcsfFh2DEMKmfl7JAqR8SAqk"hash value in c# = "FAAAAAD0AQAAAAAAAAAAAFJZUX3EUFdhFHeMZLSdlo9RxsxO"

我无法复制的一行代码是

There is one line of code which I have not been able to replicate is

BigEndianCodec.putLong(_saltBytes, 0, SecureRandomUtil.nextLong())

不太确定这行代码在做什么以及如何在c#中复制类似的逻辑

not too sure what this line of code is doing and how can I replicate the similar logic in c#

Java代码-------------

Code in 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;
}

推荐答案

BigEndianCodec.putLong(_saltBytes, 0, SecureRandomUtil.nextLong())似乎是生成一个随机的8字节值并将其写入数组(按Big Endian顺序;但是它是随机的,因此不会没关系)".

BigEndianCodec.putLong(_saltBytes, 0, SecureRandomUtil.nextLong()) Seems to be "Generate a random 8-byte value and write it into an array (in Big Endian order; but it's random, so that doesn't matter)".

所以你想要

using (RandomNumberGenerator csprng = RandomNumberGenerator.Create())
{
    csprng.GetBytes(salt);
}

在分配salt并将其传递给Rfc2898DeriveBytes'ctor之间.

Between allocating salt and passing it to Rfc2898DeriveBytes' ctor.

这篇关于.Net C#中的Liferay加密算法实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 03:25