密码加密算法:EVPKDF

EvpKDF是一种常用的密码加密算法,用于将用户密码转换成一个固定长度的密钥。EvpKDF算法的全称是“基于密码的密钥派生函数”(Password-Based Key Derivation Function),它通过在用户密码上附加一个随机盐值,然后对附加了盐值的密码进行多次哈希计算,最后将计算结果作为密钥

key和iv是根据这个算法算出来的,而不是手动加的(不过其实就是从找对称加密的key和iv变成了找evpkdf的key、salt、迭代次数和哈希算法。。)

https://www.reelshort.com

简单来说就是看见 U2FsdGVkX1 的加密参数你就有福了,直接找kdf即可

因为最后都是”Salted__” + salt + cipherText的字符串进行base64,所以前面那段总是 U2FsdGVkX1


Python代码来自于:https://gist.github.com/rafiibrahim8/0cd0f8c46896cafef6486cb1a50a16d3

import base64
import hashlib
import os

from typing import Union
from Cryptodome.Cipher import AES
from Cryptodome.Util.Padding import pad, unpad


def EVPKDF(
        password: Union[str, bytes, bytearray],
        salt: Union[bytes, bytearray],
        keySize=32,
        ivSize=16,
        iterations=1,
        hashAlgorithm="md5",
) -> tuple:
    """OpenSSL EVP Key Derivation Function
    Args:
        password (Union[str, bytes, bytearray]): Password to generate key from.
        salt (Union[bytes, bytearray]): Salt to use.
        keySize (int, optional): Output key length in bytes. Defaults to 32.
        ivSize (int, optional): Output Initialization Vector (IV) length in bytes. Defaults to 16.
        iterations (int, optional): Number of iterations to perform. Defaults to 1.
        hashAlgorithm (str, optional): Hash algorithm to use for the KDF. Defaults to 'md5'.
    Returns:
        key, iv: Derived key and Initialization Vector (IV) bytes.
    """

    assert iterations > 0, "Iterations can not be less than 1."

    if isinstance(password, str):
        password = password.encode("utf-8")

    final_length = keySize + ivSize
    key_iv = b""
    block = None

    while len(key_iv) < final_length:
        hasher = hashlib.new(hashAlgorithm)
        if block:
            hasher.update(block)
        hasher.update(password)
        hasher.update(salt)
        block = hasher.digest()
        for _ in range(1, iterations):
            block = hashlib.new(hashAlgorithm, block).digest()
        key_iv += block

    key, iv = key_iv[:keySize], key_iv[keySize:final_length]
    return key, iv


def aes_encrypt(message, password):
    # salt = bytearray([246, 92, 14, 202, 230, 221, 212, 26])  # 注意!js复制过来的情况下,要注意大端字节和小端字节
    salt = os.urandom(8)
    key, iv = EVPKDF(password, salt, 32, 16, 1, "md5")
    cipher = AES.new(key, AES.MODE_CBC, iv)
    padded_data = pad(message.encode('utf-8'), AES.block_size)
    ciphertext = cipher.encrypt(padded_data)
    result = b'Salted__' + salt + ciphertext
    return base64.b64encode(result).decode('utf-8')


def aes_decrypt(ciphertext, password):
    raw = base64.b64decode(ciphertext)
    salt = raw[8:16]
    key, iv = EVPKDF(password, salt, 32, 16, 1, "md5")
    cipher = AES.new(key, AES.MODE_CBC, iv)
    text = unpad(cipher.decrypt(raw[16:]), AES.block_size)

    return text.decode()


msg = '123456'
ps = "952605d2c779d8f04fb7ffe276bbf834"
print(aes_decrypt(aes_encrypt(msg, ps), ps))
const crypto = require('crypto');

function evpKDF(password, salt, keylen, iterations, digest) {
  return newPromise((resolve, reject) => {
    crypto.pbkdf2(password, salt, iterations, keylen, digest, (err, derivedKey) => {
      if(err) {
        reject(err);
      } else{
        resolve(derivedKey.toString('hex'));
      }
    });
  });
}

const password = 'password';
const salt = crypto.randomBytes(16).toString('hex');
const keylen = 32;
const iterations = 100000;
const digest = 'sha256';
evpKDF(password, salt, keylen, iterations, digest)
  .then((key) => {
    console.log(`密码: ${password}`);
    console.log(`盐值: ${salt}`);
    console.log(`密钥长度: ${keylen}`);
    console.log(`迭代次数: ${iterations}`);
    console.log(`哈希算法: ${digest}`);
    console.log(`转换后的密钥: ${key}`);
  })
  .catch((err) => {
    console.error(err);
  });

/*
const password = '123';
const salt = '123';
const keylen = 132;
const iterations = 100000;
const digest = 'sha256';
==>
密码: 123
盐值: 123
密钥长度: 132
迭代次数: 100000
哈希算法: sha256
转换后的密钥: 67a7a835eb2787fb9578f9082821d89039426f4ae66d64e534d4285ed83586199865d28fddc5dca5e49e14023dca614715556e2f8e88523640e91698cb47ff59542d47cdeb25f83b830f5b8918c78854fd8210f0f40ce7164618ed335a61b32c0d14cb3f862e720686466ea9069bb071e5c1d7eef984baf8b64799a222cf14275e4e1612
*/

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注