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?