По итогам чтения документации к протоколу возникла куча вопросов, по всем пунктам. Начну с криптографического слоя: 1. Почему для проверки целостности сообщения используется MAC, а не HMAC? Это было бы логичнее и безопаснее. 2. Почему используется схема Encrypt-and-Mac, а не Encrypt-then-Mac? Во-первых, она считается более безопасной, а во-вторых, позволяет отбрасывать сообщения, битые из-за ошибок на уровне транспорта, до расшифровки. 3. Почему для шифрования выбран последовательный IGE, в то время, как существует куча параллельных схем (что особенно актуально на мобилках с кучей медленных ядер). Например, использование GCM (http://en.wikipedia.org/wiki/Galois/Counter_Mode) в режиме AEAD, имплементации которого существуют во всех криптографических библиотеках, убрало бы все эти вопросы. Кроме того, он еще и аппаратно акселерируется на процессорах Intel. А учитывая, что он выбран в качестве стандарта в TLS 1.2, IEEE 802.11 ad (http://en.wikipedia.org/wiki/WiGig) и т.д., можно ждать аппаратную акселерацию и на мобильных процессорах. Что касается RPC-слоя: Зачем было изобретать еще один протокол сериализации? Уже есть ProtoBuf, поддерживающий Schema Evolution. Есть Thrift, заточенный под RPC (и также поддерживающий Schema Evolution). Есть BSON, вообще не имеющий схемы (хоть и менее компактный, чем все предыдущие). И есть Avro (имхо, самый подходящий для этой задачи), позволяющий генерировать динамическую схему и передавать ее клиенту только в случае изменения. В итоге, с задачей экономии байтиков Avro справляется гораздо лучше. Если взять пример вот с этой страницы: http://dev.stel.com/mtproto/TL (самый низ, «Пример RPC-запроса»), то запрос на Avro будет занимать 6-8 байт вместо 12, а ответ на него также будет в 1.5-2 раза короче (сорри, лень считать точнее). Так как схема передается только при изменении (что бывает, например, раз в месяц), то она не добавляет байтиков к RPC-вызовам. Честно говоря, после этих вычислений, слова «меньше байтов» выглядят несколько бледно. И самое главное: не надо писать еще одну библиотеку сериализации на всех существующих языках программирования. Дальше, собственно говоря, пошли мелочи. Если бы все предыдущие пункты были сделаны с использованием промышленных стандартов, то все, что написано ниже, отпало бы само собой: 1. Почему бы вместо CRC32 при вычислении ID поля не использовать, например, Murmur3-32 (http://en.wikipedia.org/wiki/MurmurHash), исключающий коллизии? 2. Почему бы для сериализации int’ов не использовать VarInt (возможно, с ZigZag encoding), являющийся де-факто стандартом (см., например, тут: https://developers.google.com/protocol-buffers/docs/encoding). Во-первых, он экономит байтики на строках до 16к символов (что вполне соответствует размеру поста в социальной сети/сообщения в IM и т.д.). Во-вторых, он позволяет не различать типы int и long при сериализации. В третьих, с ZigZag encoding, он позволяет компактно передавать отрицательные числа (что вполне актуально для API VK, в котором много где используются отрицательные ID групп). 3. Зачем нужно такое адское количество исключений из правил? Вот, например, мое любимое: «Существует сокращённая версия этого протокола: если клиент отправляет первым байтом (важно: только перед самым первым пакетом данных) 0xef, то после этого длина пакета кодируется одним байтом (0x01..0x7e = длина данных, делённая на 4; либо 0x7f, а затем 3 байта длины (little-endian), делённой на 4), а далее идут сами данные (порядковый номер или CRC32 не добавляются). Ответы сервера в этом случае имеют тот же вид (при этом сервер не отсылает первый байт 0xef).» Все эти исключения добавляют сложность имплементации и потенциальные баги, Имхо, выигрыш от этих хаков совершенно непропорционален затратам на разработку. 4. Почему в описании протокола нет ни слова об обработке ошибок? Работа вменяемого приложения невозможна без понимания, что пошло не так. А учитывая, что мы имеем дело с тремя слоями (транспорт, криптография, RPC), то нужны, соответственно, 3 уровня диагностики. 5. Почему в описании протокола нет ни слова о других моделях коммуникации, помимо RPC? Из описании совершенно не следует, что протокол подойдет, например, для потоковой передачи данных (может и подойдет, но это ниоткуда не следует). Это к вопросу о voice/video, который уже задавали. Резюме Разработки, претендующие на стандартизацию, обычно ведутся широким кругом экспертов с публичными обсуждениями и т.д. При этом, эксперты в криптографии отвечают за криптографические решения, эксперты в транспортных протоколах — за транспортные решения, а эксперты по байтикам — за экономию байтиков. Побочным результатом этих обсуждений является документированная мотивация выбора тех или иных решений. Я вполне допускаю, что у разработчиков протокола есть ответы на все мои вопросы (тем более, что я не претендую на экспертизу в криптографии/транспортах), но без ответов на вопросы я вынужден оценивать эту разработку со своей колокольни (как, впрочем, и другие потенциальные разработчики). А для меня протокол выглядит неоптимальным, избыточно сложным и недостаточно документированным. В общем, хорошим упражнением для имеющих время и желание в нем поковыряться, но, простите за бедность речи, адским геморроем при необходимости инвестирования в разработку под этот протокол и дальнейшего использовании в коммерческих продуктах.
По итогам чтения документации к протоколу возникла куча вопросов, по всем пунктам. Начну с криптографического слоя: 1. Почему нет никакого механизма проверки целостности сообщения? Мало того, что отсутствие MAC добавляет геморроя при выявлении транспортных ошибок, оно еще и ведет к простору в использовании CCA (http://en.wikipedia.org/wiki/Chosen-ciphertext_attack). Ну и в целом, я не понимаю, как можно в 21 веке использовать слова «большая криптоустойчивость» по отношении к чему-то, не выполняющему требования Authenticated Encryption (http://en.wikipedia.org/wiki/Authenticated_encryption). Насколько я помню, после эпик фейла под названием WEP, не было разработано ни одного криптографического стандарта, не требующего передачи MAC. 2. Почему для шифрования выбран последовательный IGE, в то время, как существует куча параллельных схем (что особенно актуально на мобилках с кучей медленных ядер). Например, прекрасный GCM (http://en.wikipedia.org/wiki/Galois/Counter_Mode), имплементации которого существуют во всех криптографических библиотеках. Кроме того, он еще и аппаратно акселерируется на процессорах Intel. А учитывая, что он выбран в качестве стандарта в TLS 1.2, IEEE 802.11 ad (http://en.wikipedia.org/wiki/WiGig) и т.д., можно ждать аппаратную акселерацию и на мобильных процессорах. Кстати, GCM поддерживает режим AEAD, что заодно решает проблему целостности сообщения. Что касается RPC-слоя: 1. Зачем было изобретать еще один протокол сериализации? Уже есть ProtoBuf, поддерживающий Schema Evolution. Есть Thrift, заточенный под RPC (и также поддерживающий Schema Evolution). Есть BSON, вообще не имеющий схемы (хоть и менее компактный, чем все предыдущие). И есть Avro (имхо, самый подходящий для этой задачи), позволяющий генерировать динамическую схему и передавать ее клиенту только в случае изменения. В итоге, с задачей экономии байтиков Avro справляется гораздо лучше. Если взять пример вот с этой страницы: http://dev.stel.com/mtproto/TL (самый низ, «Пример RPC-запроса»), то запрос на Avro будет занимать 6-8 байт вместо 12, а ответ на него, по прикидкам, также будет в 1.5-2 раза короче (сорри, лень считать точнее). Так как схема передается только при изменении (что бывает, например, раз в месяц), то она не добавляет байтиков к RPC-вызовам. Честно говоря, после этих вычислений, слова «меньше байтов» выглядят несколько бледно. И самое главное: не надо писать еще одну библиотеку сериализации на всех существующих языках программирования. Дальше, собственно говоря, пошли мелочи. Если бы все предыдущие пункты были сделаны с использованием промышленных стандартов, то все, что написано ниже, отпало бы само собой: 1. Почему бы вместо CRC32 при вычислении ID поля не использовать, например, Murmur3-32 (http://en.wikipedia.org/wiki/MurmurHash), исключающий коллизии? 2. Почему бы для сериализации int’ов (везде, в том числе и при передаче длины строк) не использовать VarInt (возможно, с ZigZag encoding), являющийся де-факто стандартом (см., например, тут: https://developers.google.com/protocol-buffers/docs/encoding). Во-первых, он экономит байтики на строках до 16к символов (что вполне соответствует размеру поста в социальной сети, сообщения в IM и т.д.). Во-вторых, он позволяет не различать типы int и long при сериализации. В третьих, с ZigZag encoding, он позволяет компактно передавать отрицательные числа (что вполне актуально для API VK, в котором много где используются отрицательные ID групп). 3. Зачем нужно такое адское количество исключений из правил? Вот, например, мое любимое: «Существует сокращённая версия этого протокола: если клиент отправляет первым байтом (важно: только перед самым первым пакетом данных) 0xef, то после этого длина пакета кодируется одним байтом (0x01..0x7e = длина данных, делённая на 4; либо 0x7f, а затем 3 байта длины (little-endian), делённой на 4), а далее идут сами данные (порядковый номер или CRC32 не добавляются). Ответы сервера в этом случае имеют тот же вид (при этом сервер не отсылает первый байт 0xef).» Все эти исключения добавляют сложность имплементации и потенциальные баги, Имхо, выигрыш от этих хаков совершенно непропорционален затратам на разработку. 4. Почему в описании протокола нет ни слова об обработке ошибок? Работа вменяемого приложения невозможна без понимания, что пошло не так. А учитывая, что мы имеем дело с тремя слоями (транспорт, криптография, RPC), то нужны, соответственно, 3 уровня диагностики. 5. Почему в описании протокола нет ни слова о других моделях коммуникации, помимо RPC? Из описании совершенно не следует, что протокол подойдет, например, для потоковой передачи данных. Может и подойти, но это ниоткуда не следует(это к вопросу о voice/video, который уже задавали). Резюме Разработки, претендующие на стандартизацию, обычно ведутся широким кругом экспертов с публичными обсуждениями и т.д. При этом, эксперты в криптографии отвечают за криптографические решения, эксперты в транспортных протоколах — за транспортные решения, а эксперты по байтикам — за экономию байтиков. Побочным результатом этих обсуждений является документированная мотивация выбора тех или иных решений. Я вполне допускаю, что у разработчиков протокола есть ответы на все мои вопросы (тем более, что я не претендую на экспертизу в криптографии/транспортах), но без ответов я вынужден оценивать эту разработку со своей колокольни (как, впрочем, и другие потенциальные разработчики). А для меня протокол выглядит неоптимальным, избыточно сложным и недостаточно документированным. В общем, хорошим упражнением для имеющих время и желание в нем поковыряться, но, простите за бедность речи, адским геморроем при необходимости инвестирования в разработку под этот протокол и дальнейшего использования в коммерческих продуктах.
Дискуссии пользователя
По итогам чтения документации к протоколу возникла куча вопросов, по всем пунктам. Начну с криптографического слоя: 1. Почему для проверки целостности сообщения используется MAC, а не HMAC? Это было бы логичнее и безопаснее. 2. Почему используется схема Encrypt-and-Mac, а не Encrypt-then-Mac? Во-первых, она считается более безопасной, а во-вторых, позволяет отбрасывать сообщения, битые из-за ошибок на уровне транспорта, до расшифровки. 3. Почему для шифрования выбран последовательный IGE, в то время, как существует куча параллельных схем (что особенно актуально на мобилках с кучей медленных ядер). Например, использование GCM (http://en.wikipedia.org/wiki/Galois/Counter_Mode) в режиме AEAD, имплементации которого существуют во всех криптографических библиотеках, убрало бы все эти вопросы. Кроме того, он еще и аппаратно акселерируется на процессорах Intel. А учитывая, что он выбран в качестве стандарта в TLS 1.2, IEEE 802.11 ad (http://en.wikipedia.org/wiki/WiGig) и т.д., можно ждать аппаратную акселерацию и на мобильных процессорах. Что касается RPC-слоя: Зачем было изобретать еще один протокол сериализации? Уже есть ProtoBuf, поддерживающий Schema Evolution. Есть Thrift, заточенный под RPC (и также поддерживающий Schema Evolution). Есть BSON, вообще не имеющий схемы (хоть и менее компактный, чем все предыдущие). И есть Avro (имхо, самый подходящий для этой задачи), позволяющий генерировать динамическую схему и передавать ее клиенту только в случае изменения. В итоге, с задачей экономии байтиков Avro справляется гораздо лучше. Если взять пример вот с этой страницы: http://dev.stel.com/mtproto/TL (самый низ, «Пример RPC-запроса»), то запрос на Avro будет занимать 6-8 байт вместо 12, а ответ на него также будет в 1.5-2 раза короче (сорри, лень считать точнее). Так как схема передается только при изменении (что бывает, например, раз в месяц), то она не добавляет байтиков к RPC-вызовам. Честно говоря, после этих вычислений, слова «меньше байтов» выглядят несколько бледно. И самое главное: не надо писать еще одну библиотеку сериализации на всех существующих языках программирования. Дальше, собственно говоря, пошли мелочи. Если бы все предыдущие пункты были сделаны с использованием промышленных стандартов, то все, что написано ниже, отпало бы само собой: 1. Почему бы вместо CRC32 при вычислении ID поля не использовать, например, Murmur3-32 (http://en.wikipedia.org/wiki/MurmurHash), исключающий коллизии? 2. Почему бы для сериализации int’ов не использовать VarInt (возможно, с ZigZag encoding), являющийся де-факто стандартом (см., например, тут: https://developers.google.com/protocol-buffers/docs/encoding). Во-первых, он экономит байтики на строках до 16к символов (что вполне соответствует размеру поста в социальной сети/сообщения в IM и т.д.). Во-вторых, он позволяет не различать типы int и long при сериализации. В третьих, с ZigZag encoding, он позволяет компактно передавать отрицательные числа (что вполне актуально для API VK, в котором много где используются отрицательные ID групп). 3. Зачем нужно такое адское количество исключений из правил? Вот, например, мое любимое: «Существует сокращённая версия этого протокола: если клиент отправляет первым байтом (важно: только перед самым первым пакетом данных) 0xef, то после этого длина пакета кодируется одним байтом (0x01..0x7e = длина данных, делённая на 4; либо 0x7f, а затем 3 байта длины (little-endian), делённой на 4), а далее идут сами данные (порядковый номер или CRC32 не добавляются). Ответы сервера в этом случае имеют тот же вид (при этом сервер не отсылает первый байт 0xef).» Все эти исключения добавляют сложность имплементации и потенциальные баги, Имхо, выигрыш от этих хаков совершенно непропорционален затратам на разработку. 4. Почему в описании протокола нет ни слова об обработке ошибок? Работа вменяемого приложения невозможна без понимания, что пошло не так. А учитывая, что мы имеем дело с тремя слоями (транспорт, криптография, RPC), то нужны, соответственно, 3 уровня диагностики. 5. Почему в описании протокола нет ни слова о других моделях коммуникации, помимо RPC? Из описании совершенно не следует, что протокол подойдет, например, для потоковой передачи данных (может и подойдет, но это ниоткуда не следует). Это к вопросу о voice/video, который уже задавали. Резюме Разработки, претендующие на стандартизацию, обычно ведутся широким кругом экспертов с публичными обсуждениями и т.д. При этом, эксперты в криптографии отвечают за криптографические решения, эксперты в транспортных протоколах — за транспортные решения, а эксперты по байтикам — за экономию байтиков. Побочным результатом этих обсуждений является документированная мотивация выбора тех или иных решений. Я вполне допускаю, что у разработчиков протокола есть ответы на все мои вопросы (тем более, что я не претендую на экспертизу в криптографии/транспортах), но без ответов на вопросы я вынужден оценивать эту разработку со своей колокольни (как, впрочем, и другие потенциальные разработчики). А для меня протокол выглядит неоптимальным, избыточно сложным и недостаточно документированным. В общем, хорошим упражнением для имеющих время и желание в нем поковыряться, но, простите за бедность речи, адским геморроем при необходимости инвестирования в разработку под этот протокол и дальнейшего использовании в коммерческих продуктах.
По итогам чтения документации к протоколу возникла куча вопросов, по всем пунктам. Начну с криптографического слоя: 1. Почему нет никакого механизма проверки целостности сообщения? Мало того, что отсутствие MAC добавляет геморроя при выявлении транспортных ошибок, оно еще и ведет к простору в использовании CCA (http://en.wikipedia.org/wiki/Chosen-ciphertext_attack). Ну и в целом, я не понимаю, как можно в 21 веке использовать слова «большая криптоустойчивость» по отношении к чему-то, не выполняющему требования Authenticated Encryption (http://en.wikipedia.org/wiki/Authenticated_encryption). Насколько я помню, после эпик фейла под названием WEP, не было разработано ни одного криптографического стандарта, не требующего передачи MAC. 2. Почему для шифрования выбран последовательный IGE, в то время, как существует куча параллельных схем (что особенно актуально на мобилках с кучей медленных ядер). Например, прекрасный GCM (http://en.wikipedia.org/wiki/Galois/Counter_Mode), имплементации которого существуют во всех криптографических библиотеках. Кроме того, он еще и аппаратно акселерируется на процессорах Intel. А учитывая, что он выбран в качестве стандарта в TLS 1.2, IEEE 802.11 ad (http://en.wikipedia.org/wiki/WiGig) и т.д., можно ждать аппаратную акселерацию и на мобильных процессорах. Кстати, GCM поддерживает режим AEAD, что заодно решает проблему целостности сообщения. Что касается RPC-слоя: 1. Зачем было изобретать еще один протокол сериализации? Уже есть ProtoBuf, поддерживающий Schema Evolution. Есть Thrift, заточенный под RPC (и также поддерживающий Schema Evolution). Есть BSON, вообще не имеющий схемы (хоть и менее компактный, чем все предыдущие). И есть Avro (имхо, самый подходящий для этой задачи), позволяющий генерировать динамическую схему и передавать ее клиенту только в случае изменения. В итоге, с задачей экономии байтиков Avro справляется гораздо лучше. Если взять пример вот с этой страницы: http://dev.stel.com/mtproto/TL (самый низ, «Пример RPC-запроса»), то запрос на Avro будет занимать 6-8 байт вместо 12, а ответ на него, по прикидкам, также будет в 1.5-2 раза короче (сорри, лень считать точнее). Так как схема передается только при изменении (что бывает, например, раз в месяц), то она не добавляет байтиков к RPC-вызовам. Честно говоря, после этих вычислений, слова «меньше байтов» выглядят несколько бледно. И самое главное: не надо писать еще одну библиотеку сериализации на всех существующих языках программирования. Дальше, собственно говоря, пошли мелочи. Если бы все предыдущие пункты были сделаны с использованием промышленных стандартов, то все, что написано ниже, отпало бы само собой: 1. Почему бы вместо CRC32 при вычислении ID поля не использовать, например, Murmur3-32 (http://en.wikipedia.org/wiki/MurmurHash), исключающий коллизии? 2. Почему бы для сериализации int’ов (везде, в том числе и при передаче длины строк) не использовать VarInt (возможно, с ZigZag encoding), являющийся де-факто стандартом (см., например, тут: https://developers.google.com/protocol-buffers/docs/encoding). Во-первых, он экономит байтики на строках до 16к символов (что вполне соответствует размеру поста в социальной сети, сообщения в IM и т.д.). Во-вторых, он позволяет не различать типы int и long при сериализации. В третьих, с ZigZag encoding, он позволяет компактно передавать отрицательные числа (что вполне актуально для API VK, в котором много где используются отрицательные ID групп). 3. Зачем нужно такое адское количество исключений из правил? Вот, например, мое любимое: «Существует сокращённая версия этого протокола: если клиент отправляет первым байтом (важно: только перед самым первым пакетом данных) 0xef, то после этого длина пакета кодируется одним байтом (0x01..0x7e = длина данных, делённая на 4; либо 0x7f, а затем 3 байта длины (little-endian), делённой на 4), а далее идут сами данные (порядковый номер или CRC32 не добавляются). Ответы сервера в этом случае имеют тот же вид (при этом сервер не отсылает первый байт 0xef).» Все эти исключения добавляют сложность имплементации и потенциальные баги, Имхо, выигрыш от этих хаков совершенно непропорционален затратам на разработку. 4. Почему в описании протокола нет ни слова об обработке ошибок? Работа вменяемого приложения невозможна без понимания, что пошло не так. А учитывая, что мы имеем дело с тремя слоями (транспорт, криптография, RPC), то нужны, соответственно, 3 уровня диагностики. 5. Почему в описании протокола нет ни слова о других моделях коммуникации, помимо RPC? Из описании совершенно не следует, что протокол подойдет, например, для потоковой передачи данных. Может и подойти, но это ниоткуда не следует(это к вопросу о voice/video, который уже задавали). Резюме Разработки, претендующие на стандартизацию, обычно ведутся широким кругом экспертов с публичными обсуждениями и т.д. При этом, эксперты в криптографии отвечают за криптографические решения, эксперты в транспортных протоколах — за транспортные решения, а эксперты по байтикам — за экономию байтиков. Побочным результатом этих обсуждений является документированная мотивация выбора тех или иных решений. Я вполне допускаю, что у разработчиков протокола есть ответы на все мои вопросы (тем более, что я не претендую на экспертизу в криптографии/транспортах), но без ответов я вынужден оценивать эту разработку со своей колокольни (как, впрочем, и другие потенциальные разработчики). А для меня протокол выглядит неоптимальным, избыточно сложным и недостаточно документированным. В общем, хорошим упражнением для имеющих время и желание в нем поковыряться, но, простите за бедность речи, адским геморроем при необходимости инвестирования в разработку под этот протокол и дальнейшего использования в коммерческих продуктах.