函数应以字节切片形式返回 sha256/sha384/sha512 结果

2023-12-09

我正在编写一个函数,它将输入数据作为字符串以及要调用的 SHA 算法的位大小。它应该将生成的哈希值作为字节切片返回(第一次尝试):

package main

import (
    "crypto/sha256"
    "crypto/sha512"
    "errors"
    "fmt"
)

func main() {
    input := "This is a test."
    sha256, _ := shaSum(input, 256)
    sha384, _ := shaSum(input, 384)
    sha512, _ := shaSum(input, 512)
    fmt.Println(input, sha256, sha384, sha512)
}

func shaSum(data string, size uint) ([]byte, error) {
    input := []byte(data)
    switch size {
    case 256:
        return sha256.Sum256(input), nil
    case 384:
        return sha512.Sum384(input), nil
    case 512:
        return sha512.Sum512(input), nil
    default:
        return nil, errors.New("unsupported sha size")
    }
}

当然,这是行不通的:

$ go run shasum.go
# command-line-arguments
./shasum.go:22:23: cannot use sha256.Sum256(input) (type [32]byte) as type []byte in return argument
./shasum.go:24:23: cannot use sha512.Sum384(input) (type [48]byte) as type []byte in return argument
./shasum.go:26:23: cannot use sha512.Sum512(input) (type [64]byte) as type []byte in return argument

所以我试图从哈希函数的返回值中获取一个切片,添加[:]每次调用后(第二次尝试):

func shaSum(data string, size uint) ([]byte, error) {
    input := []byte(data)
    switch size {
    case 256:
        return sha256.Sum256(input)[:], nil
    case 384:
        return sha512.Sum384(input)[:], nil
    case 512:
        return sha512.Sum512(input)[:], nil
    default:
        return nil, errors.New("unsupported sha size")
    }
}

这也不起作用:

$ go run shasum.go
# command-line-arguments
./shasum.go:22:30: invalid operation sha256.Sum256(input)[:] (slice of unaddressable value)
./shasum.go:24:30: invalid operation sha512.Sum384(input)[:] (slice of unaddressable value)
./shasum.go:26:30: invalid operation sha512.Sum512(input)[:] (slice of unaddressable value)

所以我试图获取返回值的地址,使用括号来确保首先获取表达式的地址,然后进行切片(第三次尝试):

func shaSum(data string, size uint) ([]byte, error) {
    input := []byte(data)
    switch size {
    case 256:
        return (&(sha256.Sum256(input)))[:], nil
    case 384:
        return (&(sha512.Sum384(input)))[:], nil
    case 512:
        return (&(sha512.Sum512(input)))[:], nil
    default:
        return nil, errors.New("unsupported sha size")
    }
}

这会产生以下错误消息:

$ go run shasum.go
# command-line-arguments
./shasum.go:22:10: cannot take the address of sha256.Sum256(input)
./shasum.go:24:10: cannot take the address of sha512.Sum384(input)
./shasum.go:26:10: cannot take the address of sha512.Sum512(input)

所以我放弃并使用额外的行来解决它(第四次尝试):

func shaSum(data string, size uint) ([]byte, error) {
    input := []byte(data)
    switch size {
    case 256:
        bytes := sha256.Sum256(input)
        return bytes[:], nil
    case 384:
        bytes := sha512.Sum384(input)
        return bytes[:], nil
    case 512:
        bytes := sha512.Sum512(input)
        return bytes[:], nil
    default:
        return nil, errors.New("unsupported sha size")
    }
}

最终编译并运行。现在我想知道:为什么第四次尝试有效,而其他尝试(尤其是第三次尝试)却无效?一个好的解决方案是什么样的?有没有办法避免像第四次尝试那样增加额外的行?

EDIT:我的问题的根本问题不是如何从字节数组转换为字节切片,而是我对可寻址性概念缺乏理解,以及如何用惯用的 Go 表达我的问题的解决方案。


语言规范关于切片运算符的说明:

如果切片操作数是数组,则它必须是可寻址的,并且切片操作的结果是与数组具有相同元素类型的切片。

and 这是关于可寻址性的:

操作数必须是可寻址的,即变量、指针间接或切片索引操作;或可寻址结构操作数的字段选择器;或可寻址数组的数组索引操作。

由此可见,第四次尝试是唯一有效的。

这是一种使用以下方法的替代方法哈希值界面。

var hashFactory = map[int]func() hash.Hash{
    256: sha256.New,
    384: sha512.New384,
    512: sha512.New,
}

func shaSum(data string, size int) ([]byte, error) {
    f := hashFactory[size]
    if f == nil {
        return nil, errors.New("unsupported sha size")
    }
    h := f()
    io.WriteString(h, data)
    return h.Sum(nil), nil
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

函数应以字节切片形式返回 sha256/sha384/sha512 结果 的相关文章

随机推荐

  • 为什么 jest.spyOn() 有时不能在 Vue 组件的方法上工作?

    我看到该方法作为事件处理程序所做的更改 但是jest spyOn wrapper vm methodName 在主要情况下无法接听电话 但在某些测试中它以某种方式起作用 我怀疑可能会重新渲染 也许是因为options论证中mount 调用
  • maven 和 jboss 模块

    我是 Maven 和 jboss 的新手 所以我试图从它们之间的合作中受益 我在 Eclipse 中有一个 Maven 项目 该项目有许多依赖项 在运行时我想将它们作为 jboss 的模块提供 否则我的 EAR 将非常大 我还使用 Nexu
  • 如何在 MVC 3 中关闭客户端验证?

    我有一个客户端验证框架 我更喜欢使用它 而不是 ASP NET MVC 3 附带的现有框架 有谁知道如何在 MVC 3 中禁用它 我已经尝试过以下方法 HtmlHelper ClientValidationEnabled false Htm
  • 如何根据用户区域设置 Dygraphs 图例中的日期和时间格式

    我有一个图表 显示设备随时间的功率输出 我想格式化图例 以便它以当前用户所在位置的样式显示时间戳 例如 在美国 它会显示MM DD YY h m s am pm 并且在欧盟会显示DD MM YYYY HH MM SS ETC 目前 它是默认
  • 无法显示 HTML + SVG

    我以前用过JEditorPane 但只能显示HTML 不能显示SVG 嵌套SVG HTML也不能完整显示 然后我用JSVGCanvas 但只能显示SVG 不能显示HTML 有什么办法可以解决这个问题吗 配置JEditorPane使用JSVG
  • 我无法将 ComboBox 停靠在 TableLayoutPanel 单元格中

    请看下图 我想对接一个组合框我的 TableLayoutPanel 的单元格中的控件 组合框Dock属性设置为Fill和Anchor财产给上 下 左 右 TL DR 这是预期的行为 对于ComboBox环境Dock to Fill没有填满容
  • Spring @RequestMapping“不包含”正则表达式

    我有这个请求映射 RequestMapping value route to destination from departure html method RequestMethod GET RequestMethod HEAD 我想添加
  • C++ 中没有定义的类声明

    我对 C 没有太多经验 我对 Qt 文档中的以下几行有疑问 http qt project org doc qt 4 8 mainwindows application mainwindow h html 顶部注释后的第 4 6 行 cla
  • 如何显示 HTTP 401 基本身份验证对话框

    I am new to web development I have Android application that hosts some web pages using HTTPServer I am using Netty to de
  • python setup.py install 忽略 install_requires

    我无法使用安装本地软件包setup py 这是项目结构 my project lib local1 local1 1 0 whl index html local2 local2 1 0 whl index html setup py se
  • 如何使 HTML 有序列表的文本居中而不是数字标签居中

    我正在为页面创建一个小部件 以相反的顺序列出步骤 我计划用一个ol并设置value个人的属性li标签强制编号ol被逆转 到目前为止 一切都很好 然而 我有一个设计难题 我不确定可以用 css 解决 有了这个标记 是否可以将文本居中但保持标签
  • core-plot iOS 反转 Y 轴

    我想使用 core plot 来显示水深图 实时更新 但我不知道如何反转 Y 轴 以便 X 轴 代表时域 位于顶部我的 UIView 和 Y 轴以正值向底部增长 EDIT 如果我能像这样画轴那就更好了 X轴是时间 Y 轴从 0 到 X X
  • 如何在 Javascript 中获取 pdf 中选定的文本?

    我正在编写一个 Chrome 扩展来操作 pdf 文件 所以我想获取 pdf 中选定的文本 我怎样才能做到这一点 像这样的东西 您可以使用内部未记录的命令内置 PDF 查看器 以下是内容脚本的示例 function getPdfSelect
  • 如何判断两个向量之间的角度是外角还是内角?

    我知道如何找出两个向量之间的角度 但它总是给我内角 但我希望它总是给我逆时针方向的角度 即使它大于 180 度 我正在使用 C 但这并不重要 因为我需要了解理论 This is what I am using now 您正在寻找atan2
  • 使用 Powershell 自动执行 IE 确认提示

    我有一个很好的 powershell 脚本 可以为我女儿自动创建一个特定的网站 最近他们更改了网站并添加了一个不错的新功能 可以将我的脚本速度提高 10 倍 问题是他们用来激活此功能的输入类型会弹出一个确认对话框 HTML 看起来像这样
  • Swagger:<字符串,对象> 的映射

    我需要使用 Swagger 记录一个 API 该 API 使用对象映射作为输入和输出 并通过字符串键进行索引 Example a property foo property 1 a string 1 property 2 a string
  • 如何探索和修改从 tf.keras.preprocessing.image_dataset_from_directory() 创建的数据集?

    这是我使用该函数的方式 dataset tf keras preprocessing image dataset from directory main directory labels inferred image size 299 29
  • 范围从开始>结束

    for x in line x1 line x2 这不适用于以下情况x1 gt x2 所以我使用这个解决方法 for x in cmp min line x1 line x2 cmp max line x1 line x2 这很好 直到我需
  • 审核日志删除的最佳方法是什么?

    连接字符串上的用户 ID 不是变量 并且与程序的用户 ID 例如可以是 GUID 不同 如果连接字符串的用户 ID 是静态的 如何审核日志删除 记录插入 更新 删除的最佳位置是通过触发器 但是使用静态连接字符串 很难记录谁删除了某些内容 还
  • 函数应以字节切片形式返回 sha256/sha384/sha512 结果

    我正在编写一个函数 它将输入数据作为字符串以及要调用的 SHA 算法的位大小 它应该将生成的哈希值作为字节切片返回 第一次尝试 package main import crypto sha256 crypto sha512 errors f