2015-07-23 3 views
2

Я пытаюсь использовать открытый ключ SSH (x.crypto.ssh.PublicKey, сгенерированный разбор authorized_keys) и извлечь из него простой старый crypto.rsa.PublicKey (я знаю, что ключ имеет тип ssh-rsa). Это означает, что в ssh-land ключ имеет (неэкспортированный) тип rsaPublicKey.Каков правильный способ извлечения непортализованных полей из типа Голанг?

Используя любой reflect.Interface() или простой старый fmt.Sprintf("%v") я могу получить значение, которое выглядит как:

&{133141753607255377833524803712241410600224583899447743985716492314976605735038858392516407436607315136967439536840885454950028631410155683051419836325912444338003188332463816050354540934271243064035037856360864190161298769948076508355604915775510460445701536855931828420791030023079646791573156484306628882221 35} 

Я знаю, читая исходный пакет SSH, что ssh.rsaPublickey фактически определяется как тип Я хочу:

type rsaPublicKey rsa.PublicKey 

и поэтому это значение уже вещь, которую я хочу. (На самом деле, я могу, используя "%+v", даже видеть, что его поля (конечно же) под названием N и E.)

Моя проблема заключается в том, что я не знаю, лучший способ заставить Go верить, что это в fact a rsa.PublicKey, чем извлечь каждое из этих чисел в строки с помощью fmt.Sscan, а затем конвертировать в big.Int и int соответственно, а затем использовать те два значения, которые я получил только как модуль и показатель, чтобы создать новый rsa.PublicKey.

Это работает, но кажется невероятно неприятным. Я получаю это, поскольку он не поддерживается, вероятно, нет прямого маршрута, но, конечно, есть лучший способ получить поля, а не путем преобразования их печатных представлений.

ssh.PublicKey действительно есть Marshal() функцию, но это дает мне представление проволоки формата, и если я прохожу там, ну, я предполагаю, что это позволяет избежать злоупотреблений системы типа, но я просто в конечном итоге писать свои собственные байты -stream-to-big-Int-to-RSA, который, похоже, не помогает. В этот момент я мог бы также начать с файла authorized_keys и проанализировать его сам, и это тоже кажется глупым.

Каков правильный способ сделать это?

ответ

1

Вы можете использовать reflect преобразовать это значение интерфейса обратно к исходному rsa.PublicKey:

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

Детская площадка с аналогичным примером: http://play.golang.org/p/bcYhYHrIl_.

+0

Это работает только потому, что все находится внутри пакета 'main', иначе он будет паниковать во время выполнения. – evanmcdonnal

+2

@evanmcdonnal: прекратите комментировать, если вы не попробовали это. Это работает и примерно эквивалентно моему ответу. Я пробовал оба этих метода непосредственно с пакетом ssh. Ainar-G, хорошая идея в «Convert», я забыл об этом в пакете отражения. – JimB

+1

Это, безусловно, делает трюк и не вмешивается в отдельные поля. Это довольно ужасно. Благодаря! –

0

Лучшее, что вы можете сделать, это использовать отражение для извлечения N и E значения из rsaPublicKey в ssh.PublicKey interace:

// pub, _, _, _, err := ssh.ParseAuthorizedKey(authKeyData) 
val := reflect.ValueOf(pub).Elem() 
n := val.FieldByName("N").Interface().(*big.Int) 
e := val.FieldByName("E").Interface().(int) 

rsaKey := &rsa.PublicKey{ 
    N: n, 
    E: e, 
} 
+0

Но в этой области нет 'pub', он не экспортируется. Даже если бы это было паникой во время работы. – evanmcdonnal

+1

@evanmcdonnal: no it wont panic, если это правильный тип ключа. 'pub' - это просто проанализированный' ssh.PublicKey'. http://play.golang.org/p/bhsdKWGj_u – JimB

+0

Откуда появилось сообщение 'authKeyData'? ОП сказал, что он пытается получить значение этого поля; 'ssh.rsaPublickey', вы не преодолели эту проблему, которую вы только что предоставили, он сказал, что не хочет", возможно, также начнется с файла authorized_keys и проанализирует его сам ".... – evanmcdonnal

Смежные вопросы