Я пытаюсь сгенерировать ключ c publi из go следующим образом:
reader := rand.Reader
bitSize := 2048
keypair, err := rsa.GenerateKey(reader, bitSize)
Это, кажется, работает и генерирует что-то, что имеет смысл. Затем я хочу записать опубликованную часть этого c в виде файла RSA следующим образом:
func PublicKeyToPemBytes(prvkey *rsa.PrivateKey) ([]byte, error) {
var pubkey *rsa.PublicKey
pubkey = &prvkey.PublicKey
pubkey_bytes := x509.MarshalPKCS1PublicKey(pubkey)
if pubkey_bytes == nil {
return nil, errors.New("Public key could not be serialized")
}
pubkey_pem := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: pubkey_bytes,
},
)
return pubkey_pem, nil
}
, который генерирует нечто, более или менее похожее на то, что вы ожидаете. Вот фиктивный ключ, который я сгенерировал только для того, чтобы показать:
-----BEGIN RSA PUBLIC KEY-----
MIIBCGKCAQEAMU6KIRUM2KACW7ISHRVRVPXG5YC7+D58Y26HV3TBHJCDNYE9Z8NE
S/XOJS58SCJL+6VLCH03RQWFLSSBZRDTAFGE4V0PTZXQ1ECUIVX6EIUWAVIKTQA9
7WEBNFU4MCHVLWFPULDAQOFP02M2WXUCI/DXCHH1R2QJCJWZKAUOERYDOP3+5YZI
CDHWX54T7GIAU6XV9M/5FH39EBLVDITK85/3RKRZIB/6SRBFSKQVWPNG69WJGIZU
YJYQNNKB8QXG5VCHRJ+OXITBWXYKFXBIKUIGE8AKUDL9OI2SR5I0HQ0AMLNCI9DA
SGHT6UQGZMVRKJC9/FVKLRQURLKMUL1AKWIDAQAB
-----END RSA PUBLIC KEY-----
, но на самом деле это не правильно:
$ grep -v -- ----- < remote.pub | base64 -d | dumpasn1 -
Warning: Input is non-seekable, some functionality has been disabled.
0 264: SEQUENCE {
4 257: [APPLICATION 2] {
: Error: Spurious EOC in definite-length item.
Error: Invalid data encountered at position 12: 4E 8A.
$ openssl asn1parse -in remote.pub
0:d=0 hl=4 l= 264 cons: SEQUENCE
4:d=1 hl=4 l= 257 cons: appl [ 2 ]
8:d=2 hl=2 l= 49 prim: EOC
59:d=2 hl=2 l= 8 prim: appl [ 11 ]
69:d=2 hl=2 l= 16 cons: appl [ 5 ]
71:d=3 hl=2 l= 0 prim: priv [ 19 ]
Error in encoding
140590716953024:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:../crypto/asn1/asn1_lib.c:91:
Это должно выглядеть так:
0 266: SEQUENCE {
4 257: INTEGER
: 00 FB 11 99 FF 07 33 F6 E8 05 A4 FD 3B 36 CA 68
: E9 4D 7B 97 46 21 16 21 69 C7 15 38 A5 39 37 2E
...
: [ Another 129 bytes skipped ]
265 3: INTEGER 12345
: }
, поэтому я не думаю, что генерирую файл правильно. Код маршаллинга в pkcs1. go выглядит следующим образом:
func MarshalPKCS1PublicKey(key *rsa.PublicKey) []byte {
derBytes, _ := asn1.Marshal(pkcs1PublicKey{
N: key.N,
E: key.E,
})
return derBytes
}
Я не знаю, как это работает, но я думаю, что он должен генерировать только одну последовательность c с двумя целыми числами, одним из них является N, другим E. Я не уверен, почему dumpasn1 считает, что он закодировал [ПРИЛОЖЕНИЕ 2], но ни dumpasn1, ни openssl не считают, что сгенерированное было даже допустимым ASN.1.
Если я понимаю документация для Marshal правильно, я думаю, что функция MarshalPKCS1PublicKey должна работать правильно, но по некоторым причинам это не так.
Я немного взглянул на кодировку. Для файла rsa.pub, сгенерированного openssl, он начинается:
0000000 30 82 01 0a 02 82 01 01 00 fb 11 99 ff 07 33 f6
Используя мой метод из go, он генерирует это:
0000000 30 82 01 08 62 82 01 01 00 31 4e 8a 21 15 0c d8
ключевой фрагмент информации, Я верю, что их генерирует 0x02 (INTEGER), но метод go генерирует 0x62. Этот тег 0x62 является целым числом APPLICATION / CONSTRUCTED, как описано здесь . Я не эксперт в этом, но я думаю, что это проблема. Я думаю, что это должно быть генерирование тега 0x02 (целое число) с типом тега, установленным в UNIVERSAL.
Это действительно, насколько я могу сделать самостоятельно, хотя. Может кто-нибудь сказать мне, где я мог сойти с рельсов?
- Крис
ОБНОВЛЕНИЕ: ключевой объект publi c, определенный в pkcs1. go, выглядит следующим образом:
type pkcs1PublicKey struct {
N *big.Int
E int
}
Мне было интересно, если по каким-то причинам параметры по умолчанию не работают должным образом, поэтому я планировал скопировать эту структуру и создать свой собственный метод маршала. Мой план состоял в том, чтобы поместить теги полей asn1 на N и E, но я не продвинулся слишком далеко, прежде чем это было как-то «исправлено»:
type myPublicKey struct {
N *big.Int
E int
}
func myMarshalPKCS1PublicKey(key *rsa.PublicKey) []byte {
derBytes, _ := asn1.Marshal(myPublicKey{
N: key.N,
E: key.E,
})
return derBytes
}
, поэтому я сделал именно это и угадаю, что ... если Я вызываю myMarshalPKCS1PublicKey () вместо того, что в x509, я получаю файл ASN.1, который анализирует правильно. Не только это, но и
openssl rsa -RSAPublicKey_in -in mykey.pub -text
работает - он правильно выплевывает модуль и показатель степени.
Так что что-то другое, хотя я думаю, что я просто использую копию идентичного кода , Я подтвердил это, просто заменив вызов моему маршаллеру на вызов в модуле x509, и он перестает работать. Я в тупике.