这是代码:

    package main

    import (
        "crypto/ecdsa"
        "crypto/elliptic"
        "crypto/rand"
        "fmt"
    )

    func main() {
        msg := "Any random message"
        curve := elliptic.P224()
        key, err := ecdsa.GenerateKey(curve, rand.Reader)
        if err != nil {
            fmt.Println(err)
        }
        r, s, err := ecdsa.Sign(rand.Reader, key, []byte(msg))
        if err != nil {
            fmt.Println(err)
        }
        // fmt.Println("r: ", r)
        // fmt.Println("s: ", s)

        publicKey := key.Public()
        isVerified := ecdsa.Verify(publicKey.(*ecdsa.PublicKey), []byte(msg), r, s)
        fmt.Println("isVerified: ", isVerified)
        fmt.Println("key.PublicKey: ", key.PublicKey)
        fmt.Println("key.D: ", key.D)

        fmt.Println("key.Public() : ", publicKey)
        fmt.Printf("Type of publicKey: %T\n", publicKey)//*ecdsa.PublicKey
    }
为什么在ecdsa.Verify()上调用publicKey时需要类型声明?
当我打印publicKey的类型时,它清楚地表明它是*ecdsa.PublicKey类型,即相应的函数参数所需的类型,但相反,它被解释为crypto.PublicKey类型。
这是错误消息:
./main.go:25:28: cannot use publicKey (type crypto.PublicKey) as type *ecdsa.PublicKey in argument to ecdsa.Verify: need type assertion

最佳答案

正如您在文档中注意到的那样:

  • ecdsa.PrivateKey.Public返回crypto.PublicKey
  • ecdsa.Verify要一个ecdsa.PublicKey

  • 两种类型完全不同:
  • crypto.PublicKey是一个接口(interface):它包含一个具体值和一个动态类型。在编译时,类型可以是任何东西,因此必须在运行时检查
  • (类型切换,类型断言)
  • ecdsa.PublicKey
  • 的具体类型

    接口(interface)的全部目的是接受任何实现接口(interface)的类型。在您的情况下,publicKey可以具有动态类型ecdsa.PublicKeyrsa.PublicKey甚至nil。编译器允许它们全部。
    在调用需要特定类型的函数或方法时,编译器现在将需要所请求的实际类型。这可以使用type assertiontype switch完成。
    在简单的示例中,您可能会发现它没有必要,但可以考虑在 key 生成和验证之间添加一些中介(例如允许使用不同类型的 key ),并且最终可能会使用不同的 key 基础类型(一种是ecdsa.PublicKey,另一种是rsa.PublicKey) )。 crypto.PublicKey接口(interface)允许轻松传递此 key ,但是在实际使用它时,必须检查动态类型
    最后:用*ecdsa.PublicKey动词打印时看到%T的原因是print calls reflect.TypeOf。对于docs,这是传入接口(interface)(或nil)的动态类型。

    关于go - 在函数ecdsa.Verify上输入断言,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63370048/

    10-09 05:48