【问题标题】:how to duplicate openssl_encrypt?如何复制openssl_encrypt?
【发布时间】:2015-05-24 14:01:24
【问题描述】:

我希望有人已经在 golang 中实现了这一点,因为我什至不擅长密码学。然而,在将项目从 php 移植到 golang 时,我遇到了移植 openssl_encrypt 方法的问题,发现 here。我也对source code 进行了一些研究,但无济于事。

这是我在 golang 中 implemented 的方法。这给了我输出

lvb7JwaI4OCYUrdJMm8Q9uDd9rIILnvbZKJb/ozFbwCmLKkxoJN5Zf/ODOJ/RGq5

这是我在使用 php 时需要的输出。

lvb7JwaI4OCYUrdJMm8Q9uDd9rIILnvbZKJb/ozFbwDV98XaJjvzEjBQp7jc+2DH

这是我用php生成它的函数。

$data = "This is some text I want to encrypt";
$method = "aes-256-cbc";
$password = "This is a really long key and su";
$options = 0;
$iv = "MMMMMMMMMMMMMMMM";

echo openssl_encrypt($data, $method, $password, $options, $iv);

对我来说,它看起来非常接近,我一定遗漏了一些明显的东西。

【问题讨论】:

  • PHP 输出实际上是lvb7JwaI4OCYUrdJMm8Q9uDd9rIILnvbZKJb/ozFbwDV98XaJjvzEjBQp7jc+2DH(注意最后一个符号丢失)。
  • @JasonCoco 你愿意详细说明吗?就像我上面说的,我对加密了解不多。但除此之外,这是第三方使用的加密。但是,如果您将我链接到一些关于为什么使用 CBC 不好的文章,请仔细研究并尝试改变一些人的想法。
  • 对不起,这是我的错,使用 cbc,不要使用 ecb,你根本没有使用 :) 为误导性的评论道歉,我保证在以后评论之前多睡觉!
  • @JasonCoco 没问题只是想确保我没有做愚蠢的事情。

标签: php encryption go


【解决方案1】:

您非常接近,但填充错误。根据this answer(和 PHP 文档),PHP 使用默认的 OpenSSL 填充行为,即使用所需的填充字节数作为填充字节值。

我所做的唯一更改是:

copy(plaintextblock[length:], bytes.Repeat([]byte{uint8(extendBlock)}, extendBlock))

你可以看到完整的更新代码here

【讨论】:

  • 非常感谢,一直在尝试解决这个问题。您链接到的答案帮助我更好地理解了填充。
  • 很高兴我能帮上忙。仅供参考,看起来您总是必须使用填充,因此即使输入的明文恰好是块大小的倍数,您也可能需要更改一些代码以仍然使用填充。
  • 非常感谢!节省了我很多时间
【解决方案2】:

当我在玩它时,其他人比我更容易回答,但我有一个“更好”的示例代码固定版本,它还考虑到始终需要填充(至少模拟 php 代码的作用) .

它还显示了openssl 命令行,您将使用它来执行相同的操作,如果可用,它会运行它(当然,playground 不会)。

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "encoding/base64"
    "fmt"
    "log"
    "os/exec"
    "strings"
)

func main() {
    const input = "This is some text I want to encrypt"
    fmt.Println(opensslCommand(input))
    fmt.Println(aesCBCenctypt(input))
}

func aesCBCenctypt(input string) string {
    // Of course real IVs should be from crypto/rand
    iv := []byte("MMMMMMMMMMMMMMMM")
    // And real keys should be from something like PBKDF2, RFC 2898.
    // E.g. use golang.org/x/crypto/pbkdf2 to turn a
    // "passphrase" into a key.
    key := []byte("This is a really long key and su")

    // Make sure the block size is a multiple of aes.BlockSize
    // Pad to aes.BlockSize using the pad length as the padding
    // byte. If we would otherwise need no padding we instead
    // pad an entire extra block.
    pad := (aes.BlockSize - len(input)%aes.BlockSize)
    if pad == 0 {
        pad = aes.BlockSize
    }
    data := make([]byte, len(input)+pad)
    copy(data, input)
    for i := len(input); i < len(input)+pad; i++ {
        data[i] = byte(pad)
    }

    cb, err := aes.NewCipher(key)
    if err != nil {
        log.Fatalln("error NewCipher():", err)
    }

    mode := cipher.NewCBCEncrypter(cb, iv)
    mode.CryptBlocks(data, data)
    return base64.StdEncoding.EncodeToString(data)
}

// Just for comparison, don't do this for real!
func opensslCommand(input string) string {
    iv := []byte("MMMMMMMMMMMMMMMM")
    key := []byte("This is a really long key and su")

    args := []string{"enc", "-aes-256-cbc", "-base64"}
    // "-nosalt", "-nopad"
    args = append(args, "-iv", fmt.Sprintf("%X", iv))
    args = append(args, "-K", fmt.Sprintf("%X", key))

    cmd := exec.Command("openssl", args...)
    // Show how you could do this via the command line:
    fmt.Println("Command:", strings.Join(cmd.Args, " "))

    cmd.Stdin = strings.NewReader(input)
    result, err := cmd.CombinedOutput()
    if err != nil {
        if e, ok := err.(*exec.Error); ok && e.Err == exec.ErrNotFound {
            // openssl not available
            return err.Error() // XXX
        }
        // some other error, show it and the (error?) output and die
        fmt.Println("cmd error:", err)
        log.Fatalf("result %q", result)
    }
    // Strip trailing '\n' and return it.
    if n := len(result) - 1; result[n] == '\n' {
        result = result[:n]
    }
    return string(result)
}

Playground

【讨论】:

    猜你喜欢
    • 2018-01-24
    • 2018-08-19
    • 1970-01-01
    • 2016-05-21
    • 2018-02-05
    • 2018-08-29
    • 2021-10-10
    • 2021-12-24
    • 2018-07-25
    相关资源
    最近更新 更多