duanni5726
2015-07-23 16:41
浏览 160
已采纳

从Golang类型提取未导出字段的正确方法是什么?

I'm trying to take an SSH public key (x.crypto.ssh.PublicKey, generated by parsing authorized_keys) and extract a plain old crypto.rsa.PublicKey from it (I know the key is of type ssh-rsa). That means, in ssh-land, the key is of (unexported) type rsaPublicKey.

By using either reflect.Interface() or plain old fmt.Sprintf("%v") I can get a value that looks like:

&{133141753607255377833524803712241410600224583899447743985716492314976605735038858392516407436607315136967439536840885454950028631410155683051419836325912444338003188332463816050354540934271243064035037856360864190161298769948076508355604915775510460445701536855931828420791030023079646791573156484306628882221 35}

I know, by reading the ssh package source, that ssh.rsaPublickey is in fact defined as the type I want:

type rsaPublicKey rsa.PublicKey

and therefore this value is already the thing I want. (In fact, I can, using "%+v", even see that its fields are (of course) named N and E.)

My problem is that I don't know a better way to make Go believe that this is in fact an rsa.PublicKey than to extract each of those numbers into strings with fmt.Sscan, and then convert into big.Int and int, respectively, and then use those two values I just got as the modulus and exponent to create a new rsa.PublicKey.

That works, but seems incredibly nasty. I get that since it's unexported, there's probably no direct route, but surely there's a better way to get the fields than by reconverting their printable representations.

ssh.PublicKey does have a Marshal() function, but that gives me the wire-format representation, and if I go through there, well, I guess it avoids abusing the type system, but I'd just end up writing my own byte-stream-to-big-Int-to-RSA converter there, which doesn't seem like it really helps. At that point I might just as well start with the authorized_keys file and parse it myself, and that seems dumb too.

What's the right way to do this?

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • dongmaonao0505 2015-07-23 17:23
    已采纳

    You can use reflect to convert that interface value back to the original rsa.PublicKey:

    rsaKey := reflect.ValueOf(sshKey).
        Convert(reflect.TypeOf(&rsa.PublicKey{})).Interface().(*rsa.PublicKey)
    

    Playground with a similar example: http://play.golang.org/p/bcYhYHrIl_.

    评论
    解决 无用
    打赏 举报
  • 查看更多回答(1条)

相关推荐 更多相似问题