doumeikuan6834
doumeikuan6834
2016-08-18 17:49

与私有接口比较

已采纳

I have two objects. key1 is of type *rsa.PublicKey. key2 is of type *ssh.PublicKey which is an interface hiding a *ssh.rsaPublicKey object. ssh.rsaPublicKey is defined as:

type ssh.rsaPublicKey rsa.PublicKey

And it has a few extra methods. However, I can't cast either key to an ssh.rsaPublicKey since that class is "not exported", I can't cast key2 to an rsa.PublicKey since that doesn't implement ssh.PublicKey, and I can't access the N or e from key2 because I am not supposed to know I have an rsaPublicKey object.

How am I supposed to compare that key1 and key2 are the same key?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • douyan1453 douyan1453 5年前

    As you mentioned, you can't use type assertion because you can't refer to the unexported type ssh.rsaPublicKey.

    What you want is possible with using the reflect package.

    Since rsa.PublicKey is the underlying type of ssh.rsaPublicKey, the pointed value wrapped in key2 can be converted to rsa.PublicKey. Once you obtain reflect.Value of your key2, "navigate" to the pointed value using Value.Elem(). This value is convertible to a value of type rsa.PublicKey. You may use the Value.Convert() to "dynamically", at runtime convert it to rsa.PublicKey. Once you have it, you can use reflect.DeepEquals() to do the comparison, or compare it manually.

    This is how it could look like:

    key1 := &rsa.PublicKey{N: big.NewInt(123), E: 10}
    key2, _ := ssh.NewPublicKey(&rsa.PublicKey{N: big.NewInt(123), E: 10})
    
    
    key2conv := reflect.ValueOf(key2).Elem().
        Convert(reflect.TypeOf(rsa.PublicKey{})).Interface()
    // key2conf is an interface{}, wrapping an rsa.PublicKey
    
    // Comparision with DeepEqual
    fmt.Println(reflect.DeepEqual(*key1, key2conv))
    
    // Comparing manually:
    key22 := key2conv.(rsa.PublicKey)
    fmt.Println(key1.N.Cmp(key22.N)) // Int.Cmp() returns 0 if equal
    fmt.Println(key1.E == key22.E)
    

    Note that when comparing manually, comparing the PublicKey.N field –which is of type *big.Int– you need to use the Int.Cmp() method because comparing pointers compares the memory addresses, not the pointed values. And Int.Cmp() returns 0 if the 2 values are equal.

    点赞 评论 复制链接分享

相关推荐