首页 » 操作系统 » Windows » 正文

AES-256-CBC PKCS7 SHA256 SALT PBKDF2

发布者:站点默认
2011/04/30 浏览数(2,066) 分类:Windows AES-256-CBC PKCS7 SHA256 SALT PBKDF2已关闭评论

注:OpenSSL 加密后的密文格式为「Salted__ + 8位salt + 密文」,并不是「8位salt + 16位iv + 4位iter + 密文」。iv 和 key 是根据 salt 算出来的,并未存于密文中;原则上密码需要32位,但由于密码会被 sha256 后使用,所以密码长度可以不是32位。

OpenSSL

echo "your_message_here" | openssl enc -aes-256-cbc -a -md sha256 -pbkdf2 -iter 1000 -salt -pass pass:bUGJyKOieYiy9vScxZuBC2nGshkFEc3B
echo "U2FsdGVkX198FFzAbgWbsK+NZn2IAvDjx3zF0nnq3BQ=" | openssl enc -aes-256-cbc -d -a -md sha256 -pbkdf2 -iter 1000 -salt -pass pass:bUGJyKOieYiy9vScxZuBC2nGshkFEc3B
# windows 命令行时 echo 后的字符串不要加引号!
# -p 参数可显示 iv, key

AutoHotKey v1

crypt(message, password, isEncrypt := true) {
    tempFile := A_Temp . "\input.txt"
    FileDelete, %tempFile%
    FileAppend, %message%, %tempFile%
    outFile := A_Temp . "\output.txt"
    FileDelete, %outFile%
    cmd := "cmd /c openssl enc -aes-256-cbc -a -md sha256 -pbkdf2 -iter 1000 -salt -pass pass:" . password . " -in """ . tempFile . """ -out """ . outFile . """" . (isEncrypt ? " -e" : " -d")
    RunWait, %cmd%, , Hide
    FileRead, encrypted, %outFile%
    FileDelete, %tempFile%
    FileDelete, %outFile%
    return encrypted
}
 
; 示例用法
msg := "your_message_here"
pwd := "your_password_here"
result := crypt(msg, pwd, true)
result := result != "" ? result : msg
MsgBox, 加密结果:`n%result%
decrypted := crypt(result, pwd, false)
decrypted := decrypted != "" ? decrypted : result
MsgBox, 解密结果:`n%decrypted%

注:文章 同步剪贴板内容 AutoHotKey v1 需要这里的代码。

为什么使用文件而不是 echo “string” ?因为 windows 的 echo 没有 -e 参数,处理不了有换行的多行文本。echo 多行文本时遇到换行就执行命令了,走不到后边的 openssl 。

另,以上代码使用 RunWait 调用 OpenSSL 实现,如果必须用纯 AutoHotkey 实现(不调用 openssl.exe),需要:

  1. 实现 PBKDF2-HMAC-SHA256(可用 AHK 脚本或 DLL)
  2. 实现 AES-256-CBC(可用 AHK 脚本或 DLL)
  3. 实现 PKCS7 填充
  4. 拼接 Salted__ + salt + 密文

这非常复杂,AutoHotkey 原生不支持这些算法,通常需要调用外部 DLL(如 OpenSSL DLL、Crypt32.dll、bcrypt.dll),或者用 COM 对象(如 CAPICOM),但 CAPICOM 不支持 PBKDF2-HMAC-SHA256。

推荐:用 openssl.exe 命令行,AutoHotkey 只做自动化。

Hammerspoon lua

function crypt(message, password, isEncrypt)
    -- 1. 写入临时文件
    local tmpfile = os.tmpname()
    local f = io.open(tmpfile, "w")
    f:write(message)
    f:close()

    -- 2. 构造 openssl 命令
    local mode = isEncrypt == false and "-d" or "-e"
    local cmd = string.format(
        [[openssl enc -aes-256-cbc -a -md sha256 -pbkdf2 -iter 1000 -salt -pass pass:%s -in "%s" %s]],
        password, tmpfile, mode
    )

    -- 3. 执行命令
    local output, status = hs.execute(cmd, true)

    -- 4. 删除临时文件
    os.remove(tmpfile)

    -- 5. 返回结果
    return status and output or nil
end

-- 示例用法
local message = [[
line1
line2
line3
]]
local password = "your_password_here"

-- 加密
local encrypted = crypt(message, password)
if encrypted then
    hs.alert.show("加密结果:\n" .. encrypted)
    print("加密结果:\n" .. encrypted)
else
    hs.alert.show("加密失败")
    print("加密失败")
end

-- 解密
local decrypted = crypt(encrypted, password, false)
if decrypted then
    hs.alert.show("解密结果:\n" .. decrypted)
else
    hs.alert.show("解密失败")
end

注:使用 openssl.exe 命令,Hammerspoon 只做自动化,理由同上边 AutoHotKey。另,同步剪贴板内容 Hammerspoon需要这里的代码。

PHP

// 加密函数
function encrypt($data, $password, $iterations = 1000) {
    $salt = random_bytes(8); // 生成指定长度的随机盐值
    $derived = deriveKeyAndIV($password, $salt, $iterations); // 派生密钥和 IV
    $key = $derived['key'];
    $iv = $derived['iv'];
    $encrypted = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); // 加密数据
    return base64_encode("Salted__" . $salt . $encrypted); // 构造 OpenSSL 格式的密文并 Base64 编码
}

// 解密函数
function decrypt($encryptedData, $password, $iterations = 1000) {
    $data = base64_decode($encryptedData); // 解码 Base64 数据
    if (substr($data, 0, 8) !== "Salted__") {
        throw new Exception("Invalid encrypted data format.");
    } 
    $salt = substr($data, 8, 8); // 提取盐值(8 字节)
    $encrypted = substr($data, 16); // 提取加密数据
    $derived = deriveKeyAndIV($password, $salt, $iterations); // 派生密钥和 IV
    $key = $derived['key'];
    $iv = $derived['iv'];
    return openssl_decrypt($encrypted, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); // 解密数据
}

// 使用 PBKDF2 派生密钥和 IV
function deriveKeyAndIV($password, $salt, $iterations = 1000, $keySize = 32, $ivSize = 16) {
    $derived = hash_pbkdf2('sha256', $password, $salt, $iterations, $keySize + $ivSize, true);
    $key = substr($derived, 0, $keySize);
    $iv = substr($derived, $keySize, $ivSize);
    return ['key' => $key, 'iv' => $iv];
}
点击返回顶部
  1. 留言
  2. 联系方式