jeudi 23 juillet 2015

What's the proper way to extract unexported fields from a Golang type?

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?





Aucun commentaire:

Enregistrer un commentaire