Life.net加密算法在.Net中的实现c#

时间:2017-02-13 18:08:54

标签: c# liferay pbkdf2

我正在尝试在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];

}

}

c#中的代码

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

1 个答案:

答案 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'之间构造函数。