I have a problem converting UTF8 encoded char array to CP1250 encoded char array.
I tried making a static iconv lib, but when compiling my UTF8->CP1250 code it always fail with
1>foo.obj : error LNK2001: unresolved external symbol libiconv_close
1>foo.obj : error LNK2001: unresolved external symbol libiconv_open
1>foo.obj : error LNK2001: unresolved external symbol libiconv
I also tried a lot of compiled static libraries, but always the same error.
Doesn't matter if /MD or /MT is set.
I do not insist on using iconv. Is there any other simple solution for this problem? Thanks
Since you're coding in Windows, why not use the Windows API. Use MultiByteToWideChar to convert losslessly up to UTF-16. Then use WideCharToMultiByte to convert down to e.g. CP 1250.
Addendum: the code below seems to work OK.
#include <assert.h> // assert
#include <iostream> // std::wcout, std::wcerr
#include <iterator> // std::begin, std::end
#include <string> // std::string, std::wstring
#include <stddef.h> // ptrdiff_t
#include <stdexcept> // std::system_error
#include <stdlib.h> // EXIT_SUCCESS
#include <string.h> // memcmp
#include <system_error> // std::system_error etc.
// Example of how to include Microsoft's <windows.h>.
// More support stuff is generally needed for more serious code.
#undef UNICODE
#define UNICODE
#undef NOMINMAX
#define NOMINMAX
#undef STRICT
#define STRICT
#include <windows.h> // E_FAIL, etc.
namespace cppx {
using std::begin;
using std::end;
using std::error_code;
using std::string;
using std::system_error;
using std::system_category;
typedef unsigned char Byte;
typedef ptrdiff_t Size;
template< class Type >
auto size( Type const& c )
-> Size
{ return end( c ) - begin( c ); }
auto hopefully( bool const condition ) -> bool { return condition; }
auto fail(
string const& message,
int const code = 0
)
-> bool
{
throw system_error(
error_code( code, system_category() ), message
);
}
} // namespace cppx
namespace data {
using cppx::Byte;
using cppx::hopefully;
using cppx::fail;
using std::string;
using std::wstring;
char const utf8_bom[] = "\xEF\xBB\xBF";
template< class Type, int n >
auto dummy()
-> Type&
{ static Type the_dummy; return the_dummy; }
auto utf16_from_utf8( char const* bytes, int length )
-> wstring
{
if( length >= 3 && ::memcmp( bytes, utf8_bom, 3 ) == 0 )
{
bytes += 3; length -= 3;
}
assert( length >= 0 );
if( length == 0 ) { return L""; }
int const buffer_size = ::MultiByteToWideChar(
CP_UTF8,
0, // flags, must be 0 for UTF-8
bytes,
length,
nullptr, // output buffer
0 // buffer size
);
hopefully( buffer_size > 0 )
|| fail( "MultiByteToWideChar (1st call)", ::GetLastError() );
wstring result( buffer_size, L'#' );
int const n_encoding_values = ::MultiByteToWideChar(
CP_UTF8,
0, // flags, must be 0 for UTF-8
bytes,
length,
&result[0], // output buffer
buffer_size
);
hopefully( n_encoding_values > 0 )
|| fail( "MultiByteToWideChar (2nd call)", ::GetLastError() );
assert( n_encoding_values <= buffer_size );
result.resize( n_encoding_values ); // Possible down-sizing.
return result;
}
auto utf16_from_utf8( Byte const* const bytes, int const length )
-> wstring
{
return utf16_from_utf8( reinterpret_cast<char const*>( bytes ), length );
}
auto sbcs_from(
wchar_t const* const s,
int const length,
unsigned const codepage = ::GetACP(),
bool& used_default_char = dummy<bool, 1>()
)
-> string
{
assert( codepage != CP_UTF8 );
if( length == 0 ) { return ""; }
DWORD const flags = WC_NO_BEST_FIT_CHARS; // Must be 0 for UTF-8.
char const* const default_char = "\x7F"; // ASCII DEL
int const buffer_size = WideCharToMultiByte(
codepage,
flags,
s,
length,
nullptr, // buffer
0, // buffer size
default_char,
nullptr
);
hopefully( buffer_size > 0 )
|| fail( "WideCharToMultiByte (1st call)", ::GetLastError() );
string result = string( buffer_size, '#' );
BOOL defaulted = false;
int const n_bytes = WideCharToMultiByte(
codepage,
flags,
s,
length,
&result[0], // buffer
buffer_size,
default_char,
&defaulted
);
hopefully( n_bytes > 0 )
|| fail( "WideCharToMultiByte (2nd call)", ::GetLastError() );
assert( n_bytes <= buffer_size );
result.resize( n_bytes );
used_default_char = !!defaulted;
return result;
}
auto sbcs_from(
wstring const& s,
unsigned const codepage = ::GetACP(),
bool& used_default_char = dummy<bool, 1>()
)
-> string
{
if( s.length() == 0 ) { return ""; }
return sbcs_from( &s[0], s.length(), codepage, used_default_char );
}
} // namespace data
void cpp_main()
{
using cppx::Byte;
using cppx::fail;
using cppx::size;
using std::string;
using std::wstring;
auto const infobox = MB_ICONINFORMATION | MB_SETFOREGROUND;
Byte const utf8_bytes[] = // UTF-8 with BOM, as if from a file.
{
0xEF, 0xBB, 0xBF, 0x42, 0x6C, 0xC3, 0xA5, 0x62, 0xC3, 0xA6,
0x72, 0x73, 0x79, 0x6C, 0x74, 0x65, 0x74, 0xC3, 0xB8, 0x79,
0x21, 0x20, 0xE6, 0x97, 0xA5, 0xE6, 0x9C, 0xAC, 0xE5, 0x9B,
0xBD, 0x20, 0xD0, 0xBA, 0xD0, 0xBE, 0xD1, 0x88, 0xD0, 0xBA,
0xD0, 0xB0, 0x21, 0x0D, 0x0A, 0x0D, 0x0A, 0x48, 0x75, 0x6E,
0x67, 0x61, 0x72, 0x69, 0x61, 0x6E, 0x20, 0x61, 0x6C, 0x70,
0x68, 0x61, 0x62, 0x65, 0x74, 0x3A, 0x0D, 0x0A, 0x41, 0x20,
0xC3, 0x81, 0x20, 0x42, 0x20, 0x43, 0x20, 0x43, 0x73, 0x20,
0x44, 0x20, 0x44, 0x7A, 0x20, 0x44, 0x7A, 0x73, 0x20, 0x45,
0x20, 0xC3, 0x89, 0x20, 0x46, 0x20, 0x47, 0x20, 0x47, 0x79,
0x20, 0x48, 0x20, 0x49, 0x20, 0xC3, 0x8D, 0x20, 0x4A, 0x20,
0x4B, 0x20, 0x4C, 0x20, 0x4C, 0x79, 0x20, 0x4D, 0x20, 0x4E,
0x0D, 0x0A, 0x4E, 0x79, 0x20, 0x4F, 0x20, 0xC3, 0x93, 0x20,
0xC3, 0x96, 0x20, 0xC5, 0x90, 0x20, 0x50, 0x20, 0x28, 0x51,
0x29, 0x20, 0x52, 0x20, 0x53, 0x20, 0x53, 0x7A, 0x20, 0x54,
0x20, 0x54, 0x79, 0x20, 0x55, 0x20, 0xC3, 0x9A, 0x20, 0xC3,
0x9C, 0x20, 0xC5, 0xB0, 0x20, 0x56, 0x20, 0x28, 0x57, 0x29,
0x20, 0x28, 0x58, 0x29, 0x20, 0x28, 0x59, 0x29, 0x20, 0x5A,
0x20, 0x5A, 0x73, 0x0D, 0x0A
};
wstring const text = data::utf16_from_utf8( utf8_bytes, size( utf8_bytes ) );
::MessageBox( 0, text.c_str(), L"Original text:", infobox );
string const sbcs_text = data::sbcs_from( text, 1250 );
WORD const hungarian = MAKELANGID(
LANG_HUNGARIAN, SUBLANG_HUNGARIAN_HUNGARY
);
DWORD const hungarian_locale_id = MAKELCID( hungarian, SORT_DEFAULT );
SetThreadLocale( hungarian_locale_id )
|| fail( "SetThreadLocale", ::GetLastError() );
DWORD thread_cp = 0;
::GetLocaleInfo(
::GetThreadLocale(), // Not LOCALE_USER_DEFAULT,
LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
reinterpret_cast<wchar_t*>( &thread_cp ),
sizeof( thread_cp )/sizeof( wchar_t )
)
|| fail( "GetLocaleInfo", ::GetLastError() );
//::MessageBox( 0, std::to_wstring( thread_cp ).c_str(), L"Codepage:", MB_SETFOREGROUND );
assert( thread_cp == 1250 );
::MessageBoxA( 0, sbcs_text.c_str(), "SBCS codepage 1250 text:", infobox );
}
auto main()
-> int
{
using namespace std;
try
{
cpp_main();
return EXIT_SUCCESS;
}
catch( system_error const& x )
{
auto const code = x.code().value();
cerr << "!" << x.what() << " (code: " << code << ")" << endl;
return code;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
return E_FAIL;
}
}
Example output (Windows messageboxes):
And yes, the dummy function is an abomination, unsound and ungood, but hey. :)
Related
I want an array to have two different values, based on a condition. I can initialize the array inside the condition with the values i want.
if (myCondition == 0)
{
byte my_message[8] = {0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B};
}
else if (myCondition == 1)
{
byte my_message[8] = {0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10};
}
The problem with the previous approach is that the array has local scope, and it cannot be "seen" by the code beneath.
If I try to declare the array outside the condition with:
byte my_message[8];
then, inside the condition, I cannot use the previous way of initializing the whole array all at once.
There is no pattern in the data so I can use a for loop- inside the condition- in order to give value to each element of the array easily.
Is there a way of giving values to the array, besides the cumbersome:
if (myCondition == 0)
{
my_message[0] = {0x00};
my_message[1] = {0xAB};
my_message[2] = {0xEE};
....
}
In C you can use standard function memcpy and compound literals the following way
byte my_message[8];
if (myCondition == 0)
{
memcpy( my_message, ( byte [] ){0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B}, 8 * sizeof( byte ));
}
else if (myCondition == 1)
{
memcpy( my_message, ( byte[] ){0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10}, 8 * sizeof( byte ) );
}
In C++ it is better to use std::array instead of a raw array. For example
std::array<byte, 8> my_message;
if (myCondition == 0)
{
my_message = {0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B};
}
else if (myCondition == 1)
{
my_message = {0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10};
}
Or if to use a raw array then if the compiler supports C++ 20 then you can use the range based for loop the following way
byte my_message[8];
if (myCondition == 0)
{
for ( auto *p = my_message; auto item : {0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B} )
{
*p++ = item;
}
}
else if (myCondition == 1)
{
for ( auto *p = my_message; auto item : {0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10} )
{
*p++ = item;
}
}
Otherwise if the compiler does not support C++ 20 then this declaration
auto *p = my_message;
must be moved outside the range based for loop.
If my_message isn't changed, you could use a pointer instead of an array.
const byte my_messages[2][8] = {
{ 0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B },
{ 0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10 },
};
const byte *my_message = my_messages[ myCondition ];
If you need to be able to change my_array, I'd use the following:
const byte my_messages[2][8] = {
{ 0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B },
{ 0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10 },
};
byte my_message[8];
memcpy( my_message, my_messages[ myCondition ], sizeof( my_message ) );
You could memcpy from an anonymous array, but it's overly complicated and involves code repetition:
byte my_message[8];
if ( myCondition ) {
memcpy( my_message, ( byte[] ){ 0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10 }, sizeof( my_message) );
} else {
memcpy( my_message, ( byte[] ){ 0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B }, sizeof( my_message) );
}
You can wrap the message into the struct and use assign operator with compound literal.
You can use compound literal + memcpy
typedef unsigned char byte;
typedef struct
{
byte my_message[8];
}message_t;
int foo(int myCondition)
{
message_t my_message;
if (myCondition == 0)
{
my_message = (message_t){0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B};
}
else if (myCondition == 1)
{
my_message = (message_t){0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10};
}
return 0;
}
int bar(int myCondition)
{
byte my_message[8];
if (myCondition == 0)
{
memcpy(my_message, (byte[]){0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B}, sizeof(my_message));
}
else if (myCondition == 1)
{
memcpy(my_message, (byte[]){0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10}, sizeof(my_message));
}
return 0;
}
or you can myCondition as index:
int zoo(int myCondition)
{
byte my_message[8];
memcpy(my_message,
(byte[][8]){{0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B},
{0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10}}[myCondition],
sizeof(my_message));
return 0;
}
memcpy way looks the most efficient:
https://godbolt.org/z/d6bMfejz5
Variadic template variant:
#include <array>
#include <cstdint>
#include <cstdlib>
#include <iostream>
using byte = unsigned char;
template <typename T, typename... Ts>
std::array<T, sizeof...(Ts)> make_array(Ts... ts) {
return std::array<T, sizeof...(Ts)> { (T)ts... };
}
int main()
{
bool myCondition = false;
std::array<byte, 8> ary = myCondition
? make_array<byte>(7,6,5,4,3,2,1,0)
: make_array<byte>(0,1,2,3,4,5,6,7);
for(auto it=ary.begin(); it != ary.end(); ++it)
{
std::cout << (int)*it << std::endl;
}
return 0;
}
Why "design-in" a boolean limitation of only two conditions?
The following allows for what could be easily be less code in main(), and up to four conditions... (I've altered the values of the 4x8 bytes to bury an Easter Egg for those who are curious. Happy hunting...)
#include <stdio.h>
void show( byte *m ) { printf( "%.8s\n", m ); }
int main() {
const byte my_messages[][8] = {
{ 0x41, 0x4C, 0x4c, 0x20, 0x47, 0x4F, 0x4F, 0x44 },
{ 0x48, 0x41, 0x54, 0x45, 0x4D, 0x41, 0x52, 0x53 },
{ 0x53, 0x45, 0x4E, 0x44, 0x48, 0x45, 0x4C, 0x50 },
{ 0x54, 0x4F, 0x4F, 0x20, 0x4C, 0x41, 0x54, 0x45 },
};
byte msg[8];
# define FETCH( m, cond ) do { memcpy( m, my_messages[cond], sizeof m ); } while(0)
FETCH( msg, 0 ); show( msg ); // prove
FETCH( msg, 1 ); show( msg ); // prove
FETCH( msg, 2 ); show( msg ); // prove
FETCH( msg, 3 ); show( msg ); // prove
return 0;
}
Surprisingly, this effect is achievable using a reference to an array in C++. I'm not sure how compliant this solution is but it compiles in pedantic mode for CLANG, GCC, ICC and MSVC.
int foo(bool cond) {
byte arr0[8] = {0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B};
byte arr1[8] = {0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10};
byte (&tab)[8] = cond ? arr0 : arr1;
return tab[0];
}
See https://godbolt.org/z/P6Th7bfcn
Tried using the below code but it does not seem to work. The value of bm is null
BYTE imageData[] =
{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x0f, 0x04, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x5d, 0x52, 0x1c, 0x00, 0x00, 0x00, 0x0f, 0x50,
0x4c, 0x54, 0x45, 0x7a, 0xdf, 0xfd, 0xfd, 0xff, 0xfc, 0x39, 0x4d, 0x52, 0x19, 0x16, 0x15, 0xc3, 0x8d, 0x76, 0xc7,
0x36, 0x2c, 0xf5, 0x00, 0x00, 0x00, 0x40, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x95, 0xc9, 0xd1, 0x0d, 0xc0, 0x20,
0x0c, 0x03, 0xd1, 0x23, 0x5d, 0xa0, 0x49, 0x17, 0x20, 0x4c, 0xc0, 0x10, 0xec, 0x3f, 0x53, 0x8d, 0xc2, 0x02, 0x9c,
0xfc, 0xf1, 0x24, 0xe3, 0x31, 0x54, 0x3a, 0xd1, 0x51, 0x96, 0x74, 0x1c, 0xcd, 0x18, 0xed, 0x9b, 0x9a, 0x11, 0x85,
0x24, 0xea, 0xda, 0xe0, 0x99, 0x14, 0xd6, 0x3a, 0x68, 0x6f, 0x41, 0xdd, 0xe2, 0x07, 0xdb, 0xb5, 0x05, 0xca, 0xdb,
0xb2, 0x9a, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, sizeof(imageData));
LPVOID pImage = ::GlobalLock(hMem);
memcpy(pImage, imageData, sizeof(imageData));
IStream* pStream = NULL;
::CreateStreamOnHGlobal(hMem, FALSE, &pStream);
Gdiplus::Bitmap* bm = Gdiplus::Bitmap::FromStream(pStream, true);
I can suggest 2 ways to convert PNG to BMP.
You can use third-party libraries. In case of opencv it will be something like that:
Mat image = imread("image.png", -1);
Mat image_bmp;
image.convertTo(image_bmp, CV_8UC3);
imwrite("image.bmp", image_bmp);
In VS you can use GDI+. The following code is runnable in my VS2019.
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
#pragma comment (lib,"Gdiplus.lib")
using namespace Gdiplus;
INT GetEncoderClsid(const WCHAR* format, CLSID* pClsid); // helper function
INT main()
{
// Initialize GDI+.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
CLSID encoderClsid;
Status stat;
Image* image = new Image(L"image.png");
// Get the CLSID of the encoder.
GetEncoderClsid(L"image/bmp", &encoderClsid);
stat = image->Save(L"image.bmp", &encoderClsid, NULL);
if (stat == Ok)
printf("Image was saved successfully\n");
else
printf("Failure: stat = %d\n", stat);
delete image;
GdiplusShutdown(gdiplusToken);
return 0;
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
My current approach doesn't even produce the correct encrypted data as checked against golang's aes implementation. It also doesn't decrypt back to the original plaintext, but that's expected if the encryption step isn't working correctly. My best guess is that I'm misusing the api somehow. This is a self-contained example and can run as is.
#include <mbedtls/aes.h>
#include <vector>
void LogVec(const std::vector<uint8_t>& bin)
{
printf("(size: %i) ", bin.size());
printf("{");
for (auto& b : bin)
{
printf("%#02x, ", b);
}
printf("}\n");
}
mbedtls_aes_context AesContext;
std::vector<uint8_t> EncryptAes(std::vector<uint8_t>& iv, std::vector<uint8_t>& data)
{
std::vector<uint8_t> ivCpy(iv);
uint8_t padByte = 16 - (data.size() % 16);
for (int i = 0; i < padByte; i++)
data.push_back(padByte);
std::vector<uint8_t> ret(data.size());
mbedtls_aes_crypt_cbc(&AesContext, MBEDTLS_AES_ENCRYPT, data.size(), ivCpy.data(), data.data(), ret.data());
return ret;
}
std::vector<uint8_t> DecryptAes(const std::vector<uint8_t>& iv, std::vector<uint8_t>& data)
{
std::vector<uint8_t> ivCpy(iv);
std::vector<uint8_t> ret(data.size());
mbedtls_aes_crypt_cbc(&AesContext, MBEDTLS_AES_DECRYPT, data.size(), ivCpy.data(), data.data(), ret.data());
ret.resize(ret.size() - ret[ret.size() - 1]);
return ret;
}
int main()
{
mbedtls_aes_init(&AesContext);
std::vector<uint8_t> data = { 0x3b, 0xb1, 0x99, 0x3, 0x67, 0xf3, 0x2e, 0x1f, 0x00, 0x67, 0x38, 0xc9, 0x53, 0x92, 0xa4 };
std::vector<uint8_t> key = { 0x15, 0x1, 0xc0, 0xd0, 0xe4, 0xfd, 0xdf, 0xd7, 0x7a, 0x65, 0xf1, 0x2f, 0x45, 0x61, 0xb,
0x59, 0xd9, 0xa, 0x9c, 0x61, 0xc, 0x4, 0x76, 0xdb, 0xb, 0xbe, 0x9e, 0xe4, 0x7f, 0x8d, 0xe1, 0x46 };
std::vector<uint8_t> iv = { 0xa2, 0x78, 0xc9, 0xa4, 0xd8, 0x34, 0x88, 0x9b, 0x28, 0xdc, 0xb9, 0xe2, 0xc0, 0x58, 0x8c, 0xbc };
mbedtls_aes_setkey_enc(&AesContext, key.data(), 256);
mbedtls_aes_setkey_dec(&AesContext, key.data(), 256);
std::vector<uint8_t> dataEnc = EncryptAes(iv, data);
printf("Encrypted data: ");
LogVec(dataEnc);
//std::vector<uint8_t> dataDec = DecryptAes(iv, dataEnc);
//printf("Decrypted data: ");
//LogVec(dataDec);
getchar();
return 1;
}
Output:
Encrypted data: (size: 16) {0x5d, 0x1c, 0x9, 0x2e, 0x92, 0x8e, 0x24, 0x43, 0xfa, 0xaf, 0xb3, 0xf5, 0x37, 0x8, 0x99, 0x93, }
Expected output from using the same key, iv, data in golang:
Encrypted: 34730cba3543e5facf4b94ba9dc8a275
Before calling mbedtls_aes_crypt_cbc to encrypt you should call mbedtls_aes_setkey_enc and before calling mbedtls_aes_crypt_cbc to decrypt you should call mbedtls_aes_setkey_dec. When both are called at initialization like in your code, the latter call to setkey_dec will overwrite important data in the context structure set by setkey_enc required for encryption.
What is alternate of Rfc2898DeriveBytes in C++ without using CLR. C# sample is shared below.
string clearText="text to sign";
string EncryptionKey = "secret";
byte[] clearBytes = Encoding.UTF8.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x48, 0x71, 0x21, 0x6d, 0x21, 0x4c, 0x61, 0x62, 0x72, 0x62, 0x61, 0x62, 0x72 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
You can use PKCS5_PBKDF2_HMAC in OpenSSL.
Both of these functions are PBKDF2 function and can be used interchangeability.
Update:
Here is a sample code for you for generating similar keys in C# and OpenSSL.
C# side:
public static void Main()
{
string EncryptionKey = "secret";
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x48, 0x71, 0x21, 0x6d, 0x21, 0x4c, 0x61, 0x62, 0x72, 0x62, 0x61, 0x62, 0x72 }, 1000);
Console.WriteLine("[{0}]", string.Join(", ", pdb.GetBytes(32)));
Console.WriteLine("[{0}]", string.Join(", ", pdb.GetBytes(16)));
}
OpenSSL side:
#include <openssl/evp.h>
#include <string.h>
#include <stdlib.h>
int main(){
char secret[] = "secret";
unsigned char buf[48] = {0,};
int size = 48;
unsigned char salt[] = { 0x48, 0x71, 0x21, 0x6d, 0x21, 0x4c, 0x61, 0x62, 0x72, 0x62, 0x61, 0x62, 0x72 };
PKCS5_PBKDF2_HMAC(secret, strlen(secret), salt, sizeof(salt), 1000, EVP_sha1(), size, buf);
for (int i = 0; i < size; i++)
printf("%d ", buf[i]);
return 0;
}
Just remember in these codes iterations are just 1,000, use at least 100,000 or even 1,000,000.
I have a C++ compile-at-run-time script written for a VxWorks derived PowerPC platform, which calculates checksums for files on the embedded OS. It uses a pair of lookup tables to compute the checksum (see my code below).
I'm trying to port this script to use on Windows, because the platform dictates that I must hardcode a new script for every single file I wish to calculate the checksum for, and with what I'm trying to do that will take many hours. I need to change a bunch of files on the platform file system and provide their checksums to the system or it will refuse to load them.
I've got the code running, having changed all of the UI/output and file input stuff to work with Windows, but I'm getting the wrong checksum. On my test file, I should be getting 404f and I'm actually getting 5fb4.
Having done some research I believe I may need to convert or regenerate the lookup tables, but I have no idea how to go about this and would be grateful for any input.
Thanks!
// rt6_crc_checker.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define TRUE 1
#define FALSE 0
#define SKIP 1
#include <windows.h>
#include <iostream>
#include <cstdlib>
#include <sys/stat.h>
using namespace std;
int PL_FileExists( char *p_pPath );
void PL_itoa10( int i , char* s );
void PL_itoa16( int i , char* s );
int change_endian(int num){
int byte0, byte1, byte2, byte3;
byte0 = (num & 0x000000FF) >> 0 ;
byte1 = (num & 0x0000FF00) >> 8 ;
byte2 = (num & 0x00FF0000) >> 16 ;
byte3 = (num & 0xFF000000) >> 24 ;
return((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | (byte3 << 0));
}
/*** MAIN ***/
int main ( int argc, char **argv )
{
char carlu;
char s_nb[16];
char s_i[16];
char CRC_FIC[16];
char CRC_INF[16];
char MessPL[256];
int nb;
int size_FIC;
int size_INF;
int answ;
int CRC;
int c1;
int c2;
int rg;
int i;
int j;
FILE *l_fileIN;
FILE *l_fileOUT;
char l_line[20];
int table_h[]=
{
0x00, 0xdf, 0xbe, 0x61, 0x7c, 0xa3, 0xc2, 0x1d, 0xd3, 0x0c, 0x6d, 0xb2, 0xaf, 0x70, 0x11, 0xce,
0x8d, 0x52, 0x33, 0xec, 0xf1, 0x2e, 0x4f, 0x90, 0x5e, 0x81, 0xe0, 0x3f, 0x22, 0xfd, 0x9c, 0x43,
0x1a, 0xc5, 0xa4, 0x7b, 0x66, 0xb9, 0xd8, 0x07, 0xc9, 0x16, 0x77, 0xa8, 0xb5, 0x6a, 0x0b, 0xd4,
0x97, 0x48, 0x29, 0xf6, 0xeb, 0x34, 0x55, 0x8a, 0x44, 0x9b, 0xfa, 0x25, 0x38, 0xe7, 0x86, 0x59,
0x1f, 0xc0, 0xa1, 0x7e, 0x63, 0xbc, 0xdd, 0x02, 0xcc, 0x13, 0x72, 0xad, 0xb0, 0x6f, 0x0e, 0xd1,
0x92, 0x4d, 0x2c, 0xf3, 0xee, 0x31, 0x50, 0x8f, 0x41, 0x9e, 0xff, 0x20, 0x3d, 0xe2, 0x83, 0x5c,
0x05, 0xda, 0xbb, 0x64, 0x79, 0xa6, 0xc7, 0x18, 0xd6, 0x09, 0x68, 0xb7, 0xaa, 0x75, 0x14, 0xcb,
0x88, 0x57, 0x36, 0xe9, 0xf4, 0x2b, 0x4a, 0x95, 0x5b, 0x84, 0xe5, 0x3a, 0x27, 0xf8, 0x99, 0x46,
0x15, 0xca, 0xab, 0x74, 0x69, 0xb6, 0xd7, 0x08, 0xc6, 0x19, 0x78, 0xa7, 0xba, 0x65, 0x04, 0xdb,
0x98, 0x47, 0x26, 0xf9, 0xe4, 0x3b, 0x5a, 0x85, 0x4b, 0x94, 0xf5, 0x2a, 0x37, 0xe8, 0x89, 0x56,
0x0f, 0xd0, 0xb1, 0x6e, 0x73, 0xac, 0xcd, 0x12, 0xdc, 0x03, 0x62, 0xbd, 0xa0, 0x7f, 0x1e, 0xc1,
0x82, 0x5d, 0x3c, 0xe3, 0xfe, 0x21, 0x40, 0x9f, 0x51, 0x8e, 0xef, 0x30, 0x2d, 0xf2, 0x93, 0x4c,
0x0a, 0xd5, 0xb4, 0x6b, 0x76, 0xa9, 0xc8, 0x17, 0xd9, 0x06, 0x67, 0xb8, 0xa5, 0x7a, 0x1b, 0xc4,
0x87, 0x58, 0x39, 0xe6, 0xfb, 0x24, 0x45, 0x9a, 0x54, 0x8b, 0xea, 0x35, 0x28, 0xf7, 0x96, 0x49,
0x10, 0xcf, 0xae, 0x71, 0x6c, 0xb3, 0xd2, 0x0d, 0xc3, 0x1c, 0x7d, 0xa2, 0xbf, 0x60, 0x01, 0xde,
0x9d, 0x42, 0x23, 0xfc, 0xe1, 0x3e, 0x5f, 0x80, 0x4e, 0x91, 0xf0, 0x2f, 0x32, 0xed, 0x8c, 0x53
};
int table_l[]=
{
0x00, 0x2b, 0x57, 0x7c, 0xaf, 0x84, 0xf8, 0xd3, 0xf6, 0xdd, 0xa1, 0x8a, 0x59, 0x72, 0x0e, 0x25,
0x45, 0x6e, 0x12, 0x39, 0xea, 0xc1, 0xbd, 0x96, 0xb3, 0x98, 0xe4, 0xcf, 0x1c, 0x37, 0x4b, 0x60,
0x8b, 0xa0, 0xdc, 0xf7, 0x24, 0x0f, 0x73, 0x58, 0x7d, 0x56, 0x2a, 0x01, 0xd2, 0xf9, 0x85, 0xae,
0xce, 0xe5, 0x99, 0xb2, 0x61, 0x4a, 0x36, 0x1d, 0x38, 0x13, 0x6f, 0x44, 0x97, 0xbc, 0xc0, 0xeb,
0xbe, 0x95, 0xe9, 0xc2, 0x11, 0x3a, 0x46, 0x6d, 0x48, 0x63, 0x1f, 0x34, 0xe7, 0xcc, 0xb0, 0x9b,
0xfb, 0xd0, 0xac, 0x87, 0x54, 0x7f, 0x03, 0x28, 0x0d, 0x26, 0x5a, 0x71, 0xa2, 0x89, 0xf5, 0xde,
0x35, 0x1e, 0x62, 0x49, 0x9a, 0xb1, 0xcd, 0xe6, 0xc3, 0xe8, 0x94, 0xbf, 0x6c, 0x47, 0x3b, 0x10,
0x70, 0x5b, 0x27, 0x0c, 0xdf, 0xf4, 0x88, 0xa3, 0x86, 0xad, 0xd1, 0xfa, 0x29, 0x02, 0x7e, 0x55,
0xd4, 0xff, 0x83, 0xa8, 0x7b, 0x50, 0x2c, 0x07, 0x22, 0x09, 0x75, 0x5e, 0x8d, 0xa6, 0xda, 0xf1,
0x91, 0xba, 0xc6, 0xed, 0x3e, 0x15, 0x69, 0x42, 0x67, 0x4c, 0x30, 0x1b, 0xc8, 0xe3, 0x9f, 0xb4,
0x5f, 0x74, 0x08, 0x23, 0xf0, 0xdb, 0xa7, 0x8c, 0xa9, 0x82, 0xfe, 0xd5, 0x06, 0x2d, 0x51, 0x7a,
0x1a, 0x31, 0x4d, 0x66, 0xb5, 0x9e, 0xe2, 0xc9, 0xec, 0xc7, 0xbb, 0x90, 0x43, 0x68, 0x14, 0x3f,
0x6a, 0x41, 0x3d, 0x16, 0xc5, 0xee, 0x92, 0xb9, 0x9c, 0xb7, 0xcb, 0xe0, 0x33, 0x18, 0x64, 0x4f,
0x2f, 0x04, 0x78, 0x53, 0x80, 0xab, 0xd7, 0xfc, 0xd9, 0xf2, 0x8e, 0xa5, 0x76, 0x5d, 0x21, 0x0a,
0xe1, 0xca, 0xb6, 0x9d, 0x4e, 0x65, 0x19, 0x32, 0x17, 0x3c, 0x40, 0x6b, 0xb8, 0x93, 0xef, 0xc4,
0xa4, 0x8f, 0xf3, 0xd8, 0x0b, 0x20, 0x5c, 0x77, 0x52, 0x79, 0x05, 0x2e, 0xfd, 0xd6, 0xaa, 0x81
};
i = 0;
j = 0;
size_FIC = 0;
size_INF = 0;
c1 = 0;
c2 = 0;
rg = 0;
CRC = 0;
if ( PL_FileExists( "crc_check.ext" ) != TRUE )
{
cout << "input MISSING !";
return 0;
}
struct stat stat_buf;
int rc = stat("crc_check.ext", &stat_buf);
size_FIC = rc == 0 ? stat_buf.st_size : -1;
cout << "input found " << size_FIC << endl;
PL_itoa10 ( size_FIC , s_nb );
strcpy ( MessPL , "Size : " );
strcat ( MessPL , s_nb );
strcat ( MessPL , " K..." );
cout << MessPL << endl;
// Calculate CRC...
l_fileIN = fopen ( "crc_check.ext", "r");
if ( NULL == l_fileIN )
{
cout << "Error opening" << endl;
}
else
{
cout << "Ok will calculate CRC bear with" << endl;
c1 = 0;
c2 = 0;
rg = 0;
for ( i = 0 ; i < size_FIC ; i++ )
{
fseek ( l_fileIN , i , 0 );
if ( i % 4000 == 0 )
{
j = ( 100 * i ) / size_FIC ;
}
if ( NULL == fgets ( l_line , 2 , l_fileIN ) )
{
PL_itoa10 ( i , s_i );
strcpy ( MessPL , "READ Error ! " );
strcat ( MessPL , s_i );
cout << MessPL << endl;
i = size_FIC;
}
else
{
nb = (int) l_line[0];
if ( nb < 0 )
nb += 256;
rg = c1 ^ nb;
c1 = c2 ^ table_h[rg];
c2 = table_l[rg];
}
}
fclose(l_fileIN);
}
PL_itoa16 ( c1 , s_nb );
if ( c1 < 16 )
{
strcpy ( CRC_FIC , "0" );
strcat ( CRC_FIC , s_nb );
}
else
strcpy ( CRC_FIC , s_nb );
PL_itoa16 ( c2 , s_nb );
if ( c2 < 16 )
{
strcat ( CRC_FIC , "0" );
strcat ( CRC_FIC , s_nb );
}
else
strcat ( CRC_FIC , s_nb );
cout << CRC_FIC << endl;
}
void PL_itoa10 (int i , char* s)
{
char l_s[16];
int n = 0 , m = 0;
if ( i < 0 )
{
s[m++] = '-';
i=-i;
}
do
{
l_s[n++] = (char)('0'+(i%10));
i /= 10;
}
while ( i );
for ( --n ; n>=0 ; n--,m++ )
s[m] = l_s[n];
s[m]=0;
}
void PL_itoa16 (int i , char* s)
{
char l_s[16];
int n = 0 , m = 0;
if ( i < 0 )
{
s[m++] = '-';
i=-i;
}
do
{
if ( i%16 < 10 )
l_s[n++] = (char)('0'+(i%16));
else
l_s[n++] = (char)('a'+(i%16)-10);
i /= 16;
}
while ( i );
for ( --n ; n>=0 ; n--,m++ )
s[m] = l_s[n];
s[m]=0;
}
int PL_FileExists ( char *p_pPath )
{
FILE* l_pFich = NULL;
if (NULL == (l_pFich = fopen (p_pPath, "r")))
{
return (FALSE);
}
else
{
fclose (l_pFich);
return (TRUE);
}
}
This code is labeled as CCITT Standard CRC16 non-reflected CRC using the polynomial 0x1021. Would produced that type of table.
Try this:
static unsigned short crctable[256];
void make_crc_table( void )
{
int i, j;
unsigned long poly, c;
static const byte p[] = {0,5,12};
poly = 0L;
for ( i = 0; i < sizeof( p ) / sizeof( byte ); i++ )
{
poly |= 1L << p[i];
}
for ( i = 0; i < 256; i++ )
{
c = i << 8;
for ( j = 0; j < 8; j++ )
{
c = ( c & 0x8000 ) ? poly ^ ( c << 1 ) : ( c << 1 );
}
crctable[i] = (unsigned short) c;
}
}