Недавно ВКонтакте открыли свой новый протокол MTProto. Мне стало интересно изучить его особенности и реализовать работу с протоколом на Erlang/OTP.
Попутно я вникал в разные технологии о которых давно слышал, но не находил времени для ознакомления.
Постепенно буду выкладывать информацию, тем или иным образом связанную с MTProto, которая мне показалась интересной в процессе освоения нового протокола.
ASN.1 PER
Первое с чем я столкнулся при посещении официального сайта MTProto - http://dev.stel.com/ это публичный ключ RSA.
Что из себя представляет этот ключ и рассмотрено.
Сам ключ выглядит так: -----BEGIN RSA PUBLIC KEY----- MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6 lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+ 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB -----END RSA PUBLIC KEY-----
Ключ закодирован в формате asn.1 PER и получить его содержимое, можно командой:
vk_rsa.pub (openssl asn1parse -in public.key )
Однако, я сделаю это руками.
Отбрасываем заголовки с "---" и декодируем данные base64.
base64 decode
После декодирование, получаем следующий набор байт.
00000000 30 82 01 0a 02 82 01 01 00 c1 50 02 3e 2f 70 db |0.........P.>/p.| 00000010 79 85 de d0 64 75 9c fe cf 0a f3 28 e6 9a 41 da |y...du.....(..A.| 00000020 f4 d6 f0 1b 53 81 35 a6 f9 1f 8f 8b 2a 0e c9 ba |....S.5.....*...| 00000030 97 20 ce 35 2e fc f6 c5 68 0f fc 42 4b d6 34 86 |. .5....h..BK.4.| 00000040 49 02 de 0b 4b d6 d4 9f 4e 58 02 30 e3 ae 97 d9 |I...K...NX.0....| 00000050 5c 8b 19 44 2b 3c 0a 10 d8 f5 63 3f ec ed d6 92 |\..D+<....c?....| 00000060 6a 7f 6d ab 0d db 7d 45 7f 9e a8 1b 84 65 fc d6 |j.m...}E.....e..| 00000070 ff fe ed 11 40 11 df 91 c0 59 ca ed af 97 62 5f |....@....Y....b_| 00000080 6c 96 ec c7 47 25 55 69 34 ef 78 1d 86 6b 34 f0 |l...G%Ui4.x..k4.| 00000090 11 fc e4 d8 35 a0 90 19 6e 9a 5f 0e 44 49 af 7e |....5...n._.DI.~| 000000a0 b6 97 dd b9 07 64 94 ca 5f 81 10 4a 30 5b 6d d2 |.....d.._..J0[m.| 000000b0 76 65 72 2c 46 b6 0e 5d f6 80 fb 16 b2 10 60 7e |ver,F..]......`~| 000000c0 f2 17 65 2e 60 23 6c 25 5f 6a 28 31 5f 40 83 a9 |..e.`#l%_j(1_@..| 000000d0 67 91 d7 21 4b f6 4c 1d f4 fd 0d b1 94 4f b2 6a |g..!K.L......O.j| 000000e0 2a 57 03 1b 32 ee e6 4a d1 5a 8b a6 88 85 cd e7 |*W..2..J.Z......| 000000f0 4a 5b fc 92 0f 6a bf 59 ba 5c 75 50 63 73 e7 13 |J[...j.Y.\uPcs..| 00000100 0f 90 42 da 92 21 79 25 1f 02 03 01 00 01
asn.1 DER decode
Как следует из соответствующих стандартов, ключ сериализован asn.1 DER по следующей схеме:
RSA public key syntax ( http://tools.ietf.org/html/rfc3447#appendix-A ) RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- n publicExponent INTEGER -- e }
Каким образом asn.1 сериализует данные можно посмотреть на википедии, я лишь сделаю разбор. Если коротко, данные о структуре кодируются по схеме. Биты в байте используются для описания содержимого.
asn.1 DER decode Identifier octets octet hex binary 0000 0x30 00110000 ^^ 0(bit 8) 0(bit 7) - Class bit "Universal" 0001 00110000 ^ 1(bit 6) Content is "Constructed" 00110000 ^^^^^ 16 (bit 5 .. bit 1) Universal Class Tag SEQUENCE and SEQUENCE OF Length 0002 0x82 10000010 ^ 1(bit 8) Long form 10000010 ^^^^^^^ 2(bit 1 .. bit 7) - length octets of Contents lengths 0002 0x01 00000001 0003 0x0a 00001010 266 Length of Contents octets Content octets Identifier octets 0004 0x02 10000010 ^^ Class bits "Context-specific" 10000010 ^ Content is "Primitive" 10000010 ^^^^^ 02 Universal Class Tag "INTEGER" Length 0005 0x82 10000010 ^ 1(bit 8) Long form 10000010 ^^^^^^^ 2(bit 1 .. bit 7) - length octets of Contents lengths 0006 0x01 00000001 0007 0x01 00000001 257(0x101) Length of Contents octets Content octets (modulus data) 0008 0x00 00000000 0009 0xc1 11000001 000a 0x50 01010000 ........................ 0107 0x25 0108 0x1f Identifier octets 0109 0x02 10000010 ^^ Class bits "Context-specific" 10000010 ^ Content is "Primitive" 10000010 ^^^^^ 02 Universal Class Tag "INTEGER" Length 010a 0x03 00000011 ^ Short form 00000011 ^^^^^^^ 3 - Length of Content octets Content octets (publicExponent data) 010b 0x01 00000001 010c 0x00 00000000 010d 0x01 00000001
Modulus и Exponent
В конечном счёте мы получили два числа.
Modulus: 0xC150023E2F70DB7985DED064759CFECF0AF328E69A41DAF4D6F01B538135 A6F91F8F8B2A0EC9BA9720CE352EFCF6C5680FFC424BD634864902DE0B4B D6D49F4E580230E3AE97D95C8B19442B3C0A10D8F5633FECEDD6926A7F6D AB0DDB7D457F9EA81B8465FCD6FFFEED114011DF91C059CAEDAF97625F6C 96ECC74725556934EF781D866B34F011FCE4D835A090196E9A5F0E4449AF 7EB697DDB9076494CA5F81104A305B6DD27665722C46B60E5DF680FB16B2 10607EF217652E60236C255F6A28315F4083A96791D7214BF64C1DF4FD0D B1944FB26A2A57031B32EEE64AD15A8BA68885CDE74A5BFC920F6ABF59BA 5C75506373E7130F9042DA922179251F publicExponent: 0x010001