//=========================================================================== // Примеры к статье "ASN.1 простыми словами". // Авторское право - Юрий Строжевский, www.strozhevsky.com //=========================================================================== #include #include #include #include #include //*************************************************************************** void store_to_file(const char* name, BYTE* array, DWORD size ) { std::ofstream file( name, std::ios_base::binary ); std::ostream_iterator< char > _out_iterator( file ); std::copy( (BYTE*)array, (BYTE*)(array + size),*_out_iterator); file.flush(); file.close(); } //*************************************************************************** void asn1_REAL() { //================================================================================================ // Кодирование по основанию 10 //================================================================================================ //unsigned char rl[] = { 0x09, 0x0A, 0x03, 0x31, 0x35, 0x36, 0x32, 0x35, 0x2E, 0x45, 0x2D, 0x35 }; // "15625.E-5", base B = 10 (string encoding, got from http://asn1-playground.oss.com/) //// Использование минусового значения плюс перестановка "decimal point". //unsigned char rl[] = { 0x09, 0x0B, 0x03, 0x2D, 0x31, 0x35, 0x36, 0x32, 0x2E, 0x35, 0x45, 0x2D, 0x35 }; // "-1562.5E-5" = 0.015625, base B = 10, NR3 //// Использование плюсового значения плюс перестановка "decimal point". //unsigned char rl[] = { 0x09, 0x0B, 0x03, 0x2B, 0x31, 0x35, 0x36, 0x32, 0x2E, 0x35, 0x45, 0x2D, 0x35 }; // "+1562.5E-5" = 0.015625, base B = 10, NR3 //// Использование плюсового значения для нуля (+0) плюс оставил значение экспоненты Е = -5. //unsigned char rl[] = { 0x09, 0x07, 0x03, 0x2B, 0x30, 0x2E, 0x45, 0x2D, 0x35 }; // "+0.E-5", base B = 10, NR3 //// Использование минусового значения для нуля (-0) плюс оставил значение экспоненты Е = -5. //unsigned char rl[] = { 0x09, 0x07, 0x03, 0x2D, 0x30, 0x2E, 0x45, 0x2D, 0x35 }; // "-0.E-5", base B = 10, NR3 //// Значение без "decimal mark". //unsigned char rl[] = { 0x09, 0x09, 0x03, 0x31, 0x35, 0x36, 0x32, 0x35, 0x45, 0x2D, 0x35 }; // "15625E-5", base B = 10, NR3 //// Использование в качестве "decimal mark" символа ",". //unsigned char rl[] = { 0x09, 0x0A, 0x03, 0x31, 0x35, 0x36, 0x32, 0x35, 0x2C, 0x45, 0x2D, 0x35 }; // "15625,E-5", base B = 10, NR3 //// Использование в качестве "decimal mark" символа "," плюс добавление лидирующих двух пробелов. //unsigned char rl[] = { 0x09, 0x0C, 0x03, 0x20, 0x20, 0x31, 0x35, 0x36, 0x32, 0x35, 0x2C, 0x45, 0x2D, 0x35 }; // " 15625,E-5", base B = 10, NR3 //// Использование в качестве "decimal mark" символа ":" (0x3A). //unsigned char rl[] = { 0x09, 0x0A, 0x03, 0x31, 0x35, 0x36, 0x32, 0x35, 0x3A, 0x45, 0x2D, 0x35 }; // "15625:E-5", base B = 10, NR3 //// Использование разделителя "." плюс перестановка его на символ раньше. //unsigned char rl[] = { 0x09, 0x0A, 0x03, 0x31, 0x35, 0x36, 0x32, 0x2E, 0x35, 0x45, 0x2D, 0x35 }; // "1562.5E-5", base B = 10, NR3 //// Использование разделителя "," плюс перестановка его на символ раньше. //unsigned char rl[] = { 0x09, 0x0A, 0x03, 0x31, 0x35, 0x36, 0x32, 0x2C, 0x35, 0x45, 0x2D, 0x35 }; // "1562,5E-5", base B = 10, NR3 //// Использование разделителя "," плюс перестановка его на 2 символа раньше. //unsigned char rl[] = { 0x09, 0x0A, 0x03, 0x31, 0x35, 0x36, 0x2C, 0x32, 0x35, 0x45, 0x2D, 0x35 }; // "15,625E-5", base B = 10, NR3 //// Форма представления числа NR2 (0.15625), символ разделителя - "." //unsigned char rl[] = { 0x09, 0x08, 0x02, 0x30, 0x2E, 0x31, 0x35, 0x36, 0x32, 0x35 }; // "0.15625", base B = 10, NR2 //// Форма представления числа NR2 (0.15625), символ разделителя - "," //unsigned char rl[] = { 0x09, 0x08, 0x02, 0x30, 0x2C, 0x31, 0x35, 0x36, 0x32, 0x35 }; // "0,15625", base B = 10, NR2 //// Форма представления числа NR2 (01,15625), символ разделителя - "," //unsigned char rl[] = { 0x09, 0x08, 0x02, 0x30, 0x31, 0x2C, 0x35, 0x36, 0x32, 0x35 }; // "01,5625", base B = 10, NR2 //// Форма представления числа NR2 (01,15625), символ разделителя - "," //unsigned char rl[] = { 0x09, 0x09, 0x02, 0x20, 0x30, 0x31, 0x2C, 0x35, 0x36, 0x32, 0x35 }; // " 01,5625", base B = 10, NR2 //// Форма представления числа NR2, но с добавлением значения экспоненты (1562.5E-5). //unsigned char rl[] = { 0x09, 0x0A, 0x02, 0x31, 0x35, 0x36, 0x32, 0x2E, 0x35, 0x45, 0x2D, 0x35 }; // "1562.5E-5", base B = 10, NR2 //// Форма представления числа NR2, представление нуля в виде "0,0". //unsigned char rl[] = { 0x09, 0x04, 0x02, 0x30, 0x2C, 0x30 }; // "0,0", base B = 10, NR2 //// Форма представления числа NR2, представление нуля в виде "0.0". //unsigned char rl[] = { 0x09, 0x04, 0x02, 0x30, 0x2E, 0x30 }; // "0.0", base B = 10, NR2 //// Форма представления NR1 (015625). //unsigned char rl[] = { 0x09, 0x07, 0x01, 0x30, 0x31, 0x35, 0x36, 0x32, 0x35 }; // "015625", base B = 10, NR1 //// Форма представления NR1 (1.5625) с добавленной "decimal mark". //unsigned char rl[] = { 0x09, 0x07, 0x01, 0x31, 0x2E, 0x35, 0x36, 0x32, 0x35 }; // "015625", base B = 10, NR1 //// Форма представления NR1, но с добавленным начальным пробелом, символом 0x20 ( 015625). //unsigned char rl[] = { 0x09, 0x08, 0x01, 0x20, 0x30, 0x31, 0x35, 0x36, 0x32, 0x35 }; // " 015625", base B = 10, NR1 //// Форма представления NR1, но с добавленными двумя начальными пробелами, символом 0x20 ( 015625). //unsigned char rl[] = { 0x09, 0x09, 0x01, 0x20, 0x20, 0x30, 0x31, 0x35, 0x36, 0x32, 0x35 }; // " 015625", base B = 10, NR1 //================================================================================================ // Кодирование по основаниям 2, 8 и 16 (двоичный формат) //================================================================================================ //unsigned char rl[] = { 0x09, 0x03, 0x80, 0xfb, 0x05 }; // 0.15625, scaling factor F = 0, base B = 2, exponent = -5 //unsigned char rl[] = { 0x09, 0x03, 0x84, 0xfa, 0x05 }; // 0.15625, scaling factor F = 1, base B = 2, exponent = -6 //unsigned char rl[] = { 0x09, 0x03, 0x88, 0xf9, 0x05 }; // 0.15625, scaling factor F = 2, base B = 2, exponent = -7 //unsigned char rl[] = { 0x09, 0x03, 0x8C, 0xf8, 0x05 }; // 0.15625, scaling factor F = 3, base B = 2, exponent = -8 //unsigned char rl[] = { 0x09, 0x03, 0x90, 0xfe, 0x0a }; // 0.15625, scaling factor F = 0, base B = 8, exponent = -2 //unsigned char rl[] = { 0x09, 0x03, 0x94, 0xfe, 0x05 }; // 0.15625, scaling factor F = 1, base B = 8, exponent = -2 (shifted value according to DER encoding rules (mantissa must be odd, least bit must be 1)) //unsigned char rl[] = { 0x09, 0x03, 0x98, 0xfd, 0x14 }; // 0.15625, scaling factor F = 2, base B = 8, exponent = -3 //unsigned char rl[] = { 0x09, 0x03, 0x9c, 0xfd, 0x0a }; // 0.15625, scaling factor F = 3, base B = 8, exponent = -3 //unsigned char rl[] = { 0x09, 0x03, 0xa0, 0xfe, 0x28 }; // 0.15625, scaling factor F = 0, base B = 16, exponent = -2 //unsigned char rl[] = { 0x09, 0x03, 0xac, 0xfe, 0x05 }; // 0.15625, scaling factor F = 3, base B = 16, exponent = -2 (shifted value according to DER encoding rules (mantissa must be odd, least bit must be 1)) //unsigned char rl[] = { 0x09, 0x03, 0xa8, 0xfe, 0x0a }; // 0.15625, scaling factor F = 2, base B = 16, exponent = -2 //unsigned char rl[] = { 0x09, 0x03, 0xa4, 0xfe, 0x14 }; // 0.15625, scaling factor F = 1, base B = 16, exponent = -2 //// Кодирование числа с экспонентой, заданной с применением излишне большого вычитаемого числа. unsigned char rl[] = { 0x09, 0x07, 0x83, 0x04, 0xff, 0xff, 0xff, 0xfb, 0x05 }; // 0.15625, scaling factor F = 0, base B = 2, exponent = -5, экспонента кодируется 4-мя байтами //// Огромное значение экспоненты. //unsigned char rl[] = { 0x09, 0x07, 0x83, 0x04, 0x7f, 0xff, 0xff, 0xfb, 0x05 }; // 0.15625, scaling factor F = 0, base B = 2, exponent = -5, экспонента кодируется 4-мя байтами //================================================================================================ // Кодирование "специальных значений" //================================================================================================ //unsigned char rl[] = { 0x09, 0x01, 0x40 }; // PLUS-INFINITY //unsigned char rl[] = { 0x09, 0x01, 0x41 }; // MINUS-INFINITY //// ( ДАННОЕ ЗНАЧЕНИЕ ПОДДЕРЖИВАЕТСЯ ТОЛЬКО ПОСЛЕДНЕЙ ВЕРСИЕЙ СТАНДАРТА ) //unsigned char rl[] = { 0x09, 0x01, 0x42 }; // NOT-A-NUMBER //// ( ДАННОЕ ЗНАЧЕНИЕ ПОДДЕРЖИВАЕТСЯ ТОЛЬКО ПОСЛЕДНЕЙ ВЕРСИЕЙ СТАНДАРТА ) //unsigned char rl[] = { 0x09, 0x01, 0x43 }; // minus zero //================================================================================================ store_to_file( "asn1_real.ber", rl, sizeof(rl) ); } //*************************************************************************** void asn1_OID() { //// Кодирование "2.10000.840.135119.9.2.12301002.12132323.191919.2" //unsigned char oid[] = { 0x06, 0x15, 0xCE, 0x60, 0x86, 0x48, 0x88, 0x9F, 0x4F, 0x09, 0x02, 0x85, 0xEE, 0xE5, 0x4A, 0x85, 0xE4, 0xBF, 0x63, 0x8B, 0xDB, 0x2F, 0x02 }; // Кодирование SID в излишне длинном формате. unsigned char oid[] = { 0x06, 0x06, 0x80, 0x80, 0x01, 0x80, 0x80, 0x01 }; store_to_file("asn1_oid.ber", oid, sizeof(oid) ); } //*************************************************************************** void asn1_INTEGER() { //// Кодирование отрицательного значения (-1) //unsigned char integer[] = { 0x02, 0x01, 0xFF }; //// Кодирование положительного значения (1) //unsigned char integer[] = { 0x02, 0x01, 0x01 }; // Кодирование отрицательного значения (-136) unsigned char integer[] = { 0x02, 0x02, 0xFF, 0x78 }; //// Кодирование отрицательного значения (-8388607) //unsigned char integer[] = { 0x02, 0x03, 0x80, 0x00, 0x01 }; store_to_file("asn1_integer.ber", integer, sizeof(integer) ); } //*************************************************************************** void asn1_STRINGS() { wchar_t* test_string = L"abc_абв"; //================================================================================================= int buff_len_gen = 0; buff_len_gen = WideCharToMultiByte( 1251, 0, test_string, -1, NULL, 0, NULL, NULL ); char* test_out_gen = (char*)calloc( buff_len_gen + 2, 1) ; buff_len_gen = WideCharToMultiByte( 1251, 0, test_string, -1, test_out_gen, buff_len_gen + 2, NULL, NULL ); //================================================================================================= // Для кодирования в UnicodeString строка должна быть UTF-32 (UCS-4), или представляться // в "каноническом 4-октетном" виде. char* asn1_unicode = (char*) calloc( wcslen( test_string )*4 + 2, 1 ); asn1_unicode[0] = 0x1C; // UnicodeString asn1_unicode[1] = wcslen( test_string ) * 4; for( unsigned char i = 0; i < wcslen( test_string ); i++ ) { asn1_unicode[i*4 + 0 + 2] = 0x00; asn1_unicode[i*4 + 1 + 2] = 0x00; asn1_unicode[i*4 + 2 + 2] = ((char*)test_string)[i*2+1]; asn1_unicode[i*4 + 3 + 2] = ((char*)test_string)[i*2]; } store_to_file( "asn1_unicode.ber", (BYTE*)asn1_unicode, wcslen( test_string )*4 + 2 ); //================================================================================================= // BMPString char* asn1_bmpstring = (char*) calloc( wcslen( test_string )*2 + 2, 1 ); asn1_bmpstring[0] = 0x1E; // BMPString asn1_bmpstring[1] = wcslen( test_string ) * 2 + 0; for( unsigned char i = 0; i < wcslen( test_string ); i++ ) { asn1_bmpstring[i*2 + 0 + 2] = ((char*)test_string)[i*2+1]; asn1_bmpstring[i*2 + 1 + 2] = ((char*)test_string)[i*2]; } store_to_file( "asn1_bmpstring.ber", (BYTE*)asn1_bmpstring, wcslen( test_string )*2 + 2 ); //================================================================================================= // http://unicode.org/faq/utf_bom.html // // BOM (also called "signatures"): // =============================== // 00 00 FE FF : UTF-32, big-endian // FF FE 00 00 : UTF-32, little-endian // FE FF : UTF-16, big-endian // FF FE : UTF-16, little-endian // EF BB BF : UTF-8 (UTF-8 всегда имеет строго определенный порядок байтов и BOM служит только как сигнатура типа) // // Так как в стандарте прямо сказано, что использовать "сигнатуры" запрещено, то декодер обязан // выдавать ошибку на декодировании значений с "сигнатурой". char* asn1_bmpstring_bom = (char*) calloc( wcslen( test_string )*2 + 2 + 2, 1 ); // + BOM (4 bytes) asn1_bmpstring_bom[0] = 0x1E; // BMPString asn1_bmpstring_bom[1] = wcslen( test_string ) * 2 + 0 + 2; asn1_bmpstring_bom[2] = 0xFF; asn1_bmpstring_bom[3] = 0xFE; memcpy( asn1_bmpstring_bom + 4, test_string, wcslen( test_string ) * 2 ); store_to_file( "asn1_bmpstring_bom.ber", (BYTE*)asn1_bmpstring_bom, wcslen( test_string )*2 + 2 + 2 ); //================================================================================================= // UTF8String int buff_len = 0; buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, NULL, 0, NULL, NULL ); char* test_out = (char*)calloc( buff_len + 2, 1) ; buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, test_out, buff_len + 2, NULL, NULL ); char* asn1_utf8 = (char*) calloc( buff_len + 2, 1 ); // Уберем последний нулевой октет asn1_utf8[ 0 ] = 0x0C; // UTF8String asn1_utf8[ 1 ] = buff_len; memcpy( asn1_utf8 + 2, test_out, buff_len ); store_to_file( "asn1_utf8.ber", (BYTE*)asn1_utf8, buff_len + 2 ); //================================================================================================= // Так как в стандарте прямо сказано, что использовать "сигнатуры" запрещено, то декодер обязан // выдавать ошибку на декодировании значений с "сигнатурой". char* asn1_utf8_bom = (char*) calloc( buff_len + 2 - 1 + 3, 1 ); // Уберем последний нулевой октет asn1_utf8_bom[ 0 ] = 0x0C; // UTF8String asn1_utf8_bom[ 1 ] = buff_len-1 + 3; asn1_utf8_bom[ 2 ] = 0xEF; asn1_utf8_bom[ 3 ] = 0xBB; asn1_utf8_bom[ 4 ] = 0xBF; memcpy( asn1_utf8_bom + 2 + 3, test_out, buff_len-1 ); store_to_file( "asn1_utf8_bom.ber", (BYTE*)asn1_utf8_bom, buff_len + 2 - 1 + 3 ); //================================================================================================= } //*************************************************************************** void asn1_DATETIME() { //==================================================================== //// UTCTime, значение в формате YYMMDDHHMMSSZ (или YYMMDDHHMMSS+hhmm, или YYMMDDHHMMSS-hhmm) //// (только год, без века) //wchar_t* test_string = L"850412161500+0202"; //int buff_len = 0; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, NULL, 0, NULL, NULL ); //char* test_out = (char*)calloc( buff_len + 2, 1) ; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, test_out, buff_len + 2 - 1, NULL, NULL ); //char* asn1_date = (char*) calloc( buff_len + 2 - 1, 1 ); // Уберем последний нулевой октет //asn1_date[ 0 ] = 0x17; // UTCTime (23) //asn1_date[ 1 ] = buff_len - 1; //memcpy( asn1_date + 2, test_out, buff_len - 1 ); //store_to_file( "asn1_utctime.ber", (BYTE*)asn1_date, buff_len + 2 - 1 ); //==================================================================== //// GeneralizedTime, значение в формате YYYYMMDDHHMMSSZ (значение уже с указанием века) //wchar_t* test_string = L"19850412161500.555777+0400"; //int buff_len = 0; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, NULL, 0, NULL, NULL ); //char* test_out = (char*)calloc( buff_len + 2, 1) ; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, test_out, buff_len + 2 - 1, NULL, NULL ); //char* asn1_date = (char*) calloc( buff_len + 2 - 1, 1 ); // Уберем последний нулевой октет //asn1_date[ 0 ] = 0x18; // GeneralizedTime (24) //asn1_date[ 1 ] = buff_len - 1; //memcpy( asn1_date + 2, test_out, buff_len - 1 ); //store_to_file( "asn1_gentime.ber", (BYTE*)asn1_date, buff_len + 2 - 1 ); //==================================================================== //// Кодирование типа DATE //wchar_t* test_string = L"19850412"; //int buff_len = 0; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, NULL, 0, NULL, NULL ); //char* test_out = (char*)calloc( buff_len + 2, 1) ; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, test_out, buff_len + 2 - 1, NULL, NULL ); //char* asn1_date = (char*) calloc( buff_len + 3 - 1, 1 ); // Уберем последний нулевой октет //asn1_date[ 0 ] = 0x1F; // Длинная форма представления идентификатора //asn1_date[ 1 ] = 0x1F; // Значение идентификатора для DATE (31) //asn1_date[ 2 ] = buff_len - 1; //memcpy( asn1_date + 3, test_out, buff_len - 1 ); //store_to_file( "asn1_date.ber", (BYTE*)asn1_date, buff_len + 3 - 1 ); //==================================================================== //// Кодирование типа TIME-OF-DAY //wchar_t* test_string = L"160000"; //int buff_len = 0; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, NULL, 0, NULL, NULL ); //char* test_out = (char*)calloc( buff_len, 1) ; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, test_out, buff_len, NULL, NULL ); //char* asn1_enc = (char*) calloc( buff_len + 3 - 1, 1 ); //asn1_enc[ 0 ] = 0x1F; // Длинная форма представления идентификатора //asn1_enc[ 1 ] = 0x20; // Значение идентификатора для TIME-OF-DAY (32) //asn1_enc[ 2 ] = buff_len - 1; //memcpy( asn1_enc + 3, test_out, buff_len - 1 ); //store_to_file( "asn1_timeofday.ber", (BYTE*)asn1_enc, buff_len + 3 - 1 ); //==================================================================== //// Кодирование типа DATE-TIME //wchar_t* test_string = L"19760515160000"; //int buff_len = 0; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, NULL, 0, NULL, NULL ); //char* test_out = (char*)calloc( buff_len, 1) ; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, test_out, buff_len, NULL, NULL ); //char* asn1_enc = (char*) calloc( buff_len + 3 - 1, 1 ); //asn1_enc[ 0 ] = 0x1F; // Длинная форма представления идентификатора //asn1_enc[ 1 ] = 0x21; // Значение идентификатора для DATE-TIME (33) //asn1_enc[ 2 ] = buff_len - 1; //memcpy( asn1_enc + 3, test_out, buff_len - 1 ); //store_to_file( "asn1_datetime.ber", (BYTE*)asn1_enc, buff_len + 3 - 1 ); //==================================================================== //// Кодирование типа TIME //wchar_t* test_string = L"16:00:00Z"; //int buff_len = 0; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, NULL, 0, NULL, NULL ); //char* test_out = (char*)calloc( buff_len, 1) ; //buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, test_out, buff_len, NULL, NULL ); //char* asn1_enc = (char*) calloc( buff_len + 2 - 1, 1 ); //asn1_enc[ 0 ] = 0x0E; // TIME (14) //asn1_enc[ 1 ] = buff_len - 1; //memcpy( asn1_enc + 2, test_out, buff_len - 1 ); //store_to_file( "asn1_time.ber", (BYTE*)asn1_enc, buff_len + 2 - 1 ); //==================================================================== // Кодирование типа DURATION //wchar_t* test_string = L"01Y01M01DT01H01M01S"; wchar_t* test_string = L"1Y1M1DT1H1M1S"; int buff_len = 0; buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, NULL, 0, NULL, NULL ); char* test_out = (char*)calloc( buff_len, 1) ; buff_len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, test_string, -1, test_out, buff_len, NULL, NULL ); char* asn1_enc = (char*) calloc( buff_len + 3 - 1, 1 ); asn1_enc[ 0 ] = 0x1F; // Длинная форма представления идентификатора asn1_enc[ 1 ] = 0x22; // Значение идентификатора для DURATION (34) asn1_enc[ 2 ] = buff_len - 1; memcpy( asn1_enc + 3, test_out, buff_len - 1 ); store_to_file( "asn1_duration.ber", (BYTE*)asn1_enc, buff_len + 3 - 1 ); //==================================================================== } //*************************************************************************** void asn1_BITSEQS() { //char bitstring[] = {0x03, 0x05, 0x00, 0x81, 0x81, 0x81, 0x89 }; // Длинная битовая строка //char bitstring[] = {0x03, 0x01, 0x00 }; // Пустая битовая строка //char bitstring[] = {0x03, 0x02, 0x00, 0x00 }; // Битовая строка, содержащая только нули //char bitstring[] = {0x03, 0x02, 0x04, 0x0F }; // Битовая строка, где 4 последних бита не используются //char bitstring[] = {0x23, 0x80, 0x03, 0x02, 0x04, 0x0F, 0x04 , 0x02 , 0x81 , 0x81, 0x00, 0x00 }; // Битовая строка прямо из стандарта X.690 char bitstring[] = {0x23, 0x80, 0x03, 0x03, 0x00, 0x0A, 0x3B, 0x03, 0x05, 0x04, 0x5F, 0x29, 0x1C, 0xD0, 0x00, 0x00 }; //// Битовая строка 01 01 0F с четырьмя не используемыми битами, разбитая на 3 битовых подстроки. //char bitstring[] = {0x23, 0x80, // 0x03, 0x02, 0x00, 0x01, // 0x03, 0x02, 0x00, 0x01, // 0x03, 0x02, 0x04, 0x0F, // 0x00, 0x00 }; //// Битовая строка 01 01 0F с четырьмя не используемыми битами, разбитая на 3 битовых подстроки (явно заданная длина). //char bitstring[] = {0x23, 0x0C, // 0x03, 0x02, 0x00, 0x01, // 0x03, 0x02, 0x00, 0x01, // 0x03, 0x02, 0x04, 0x0F }; //// Усложненная версия конструктивного кодирования битовой строки. //// (в качестве одной из подстрок в свою очередь используется конструктивная строка) //char bitstring[] = {0x23, 0x80, // 0x23, 0x80, // 0x03, 0x02, 0x00, 0x01, // 0x03, 0x02, 0x01, 0x02, // Использование значения не используемых бит во вложенной подстроке // 0x00, 0x00, // 0x03, 0x02, 0x04, 0x0F, // 0x00, 0x00 }; store_to_file("asn1_bitstr.ber", (BYTE*)bitstring, sizeof( bitstring )); } //*************************************************************************** void asn1_PREFTYPES() { //// Примененная схема: //// ==================== ////World-Schema DEFINITIONS ::= ////BEGIN //// MyReal1 ::= [PRIVATE 2] IMPLICIT REAL //// MyReal2 ::= [PRIVATE 3] IMPLICIT REAL //// //// MyPrivate ::= SET { //// mr1 MyReal1, //// mr2 MyReal2 //// } ////END //// ==================== //// Здесь вложенные элементы кодируются примитивными типами. //unsigned char preftypes[] = { 0x31, 0x0A, 0xC2, 0x03, 0x80, 0xfb, 0x05, 0xC3, 0x03, 0x80, 0xfb, 0x05, }; // 0.15625 два раза // Примененная схема: // ==================== //World-Schema DEFINITIONS ::= //BEGIN // MyReal1 ::= [PRIVATE 2] REAL // MyReal2 ::= [PRIVATE 3] REAL // // MyPrivate ::= SET { // mr1 MyReal1, // mr2 MyReal2 // } //END // ==================== // Здесь вложенные элементы mr1 и mr2 кодируются конструктивными типами. unsigned char preftypes[] = { 0x31, 0x0E, 0xE2, 0x05, 0x09, 0x03, 0x80, 0xfb, 0x05, 0xE3, 0x05, 0x09, 0x03, 0x80, 0xfb, 0x05, }; // 0.15625 два раза store_to_file( "asn1_preftypes.ber", preftypes, sizeof(preftypes) ); } //*************************************************************************** void asn1_SEQUENCE() { unsigned char sequence[] = { 0x30, 0x08, 0x02, 0x01, 0x80, 0x09, 0x03, 0x80, 0xFB, 0x05 }; store_to_file( "asn1_sequence.ber", sequence, sizeof(sequence) ); } //*************************************************************************** void asn1_SET() { // См. пример в функции asn1_PREFTYPES() } //*************************************************************************** void asn1_BOOLEAN() { //// Кодирование значения TRUE //unsigned char boolean[] = { 0x01, 0x01, 0xFF }; //// Кодирование значения TRUE (еще один вариант) //unsigned char boolean[] = { 0x01, 0x01, 0x01 }; // Кодирование значения FALSE unsigned char boolean[] = { 0x01, 0x01, 0x00 }; store_to_file("asn1_boolean.ber", boolean, sizeof(boolean) ); } //*************************************************************************** void asn1_NULL() { unsigned char null[] = { 0x05, 0x00 }; store_to_file( "asn1_null.ber", null, sizeof(null) ); } //*************************************************************************** int main() { asn1_REAL(); asn1_OID(); asn1_INTEGER(); asn1_STRINGS(); asn1_DATETIME(); asn1_BITSEQS(); asn1_PREFTYPES(); asn1_SEQUENCE(); asn1_SET(); asn1_BOOLEAN(); asn1_NULL(); return 0; } //***************************************************************************