Решал схожую задачу на CentOS, использовал expat как парсер
Хэш считается примерно так:
BYTE rgbHash[GR3411LEN];
DWORD cbHash = 0;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
CryptAcquireContext(&hProv,NULL,NULL,PROV_GOST_2001_DH,CRYPT_VERIFYCONTEXT);
CryptCreateHash(hProv, CALG_GR3411, 0, 0, &hHash);
...
// из коллбэка expat
CryptHashData(*((HCRYPTHASH *)data), (const unsigned char *)buf, strlen(buf), 0);
...
cbHash=GR3411LEN;
CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0);
CryptDestroyHash(hHash);
итд.
Подпись через CryptSignMessage, типа-
CRYPT_SIGN_MESSAGE_PARA sign_params;
DWORD sp_size=sizeof(CRYPT_SIGN_MESSAGE_PARA);
memset(&sign_params,0,sp_size);
sign_params.cbSize=sp_size;
sign_params.dwMsgEncodingType=PKCS_7_ASN_ENCODING;
sign_params.pSigningCert=m_CertContext;
sign_params.HashAlgorithm.pszObjId=(CHAR *)szOID_CP_GOST_R3411;
//// get signature size
if(!CryptSignMessage(&sign_params,TRUE,1,&in,&insize,NULL,&buffer_size))
...
buffer_out=new BYTE[buffer_size];
//// sign data
if(!CryptSignMessage(&sign_params,TRUE,1,&in,&insize,buffer_out,&buffer_size))
...
Сразу скажу-основная проблема-правильно написать нормализацию xml. Можно попробовать взять где-то готовое.