| ||||
| ||||
This seems to be a good forum I cannot find similar in english anywhere else. So excuse me if I am not welcome. I need to encode some strings by means of CryptSignMessage, everything works fine without error but the encoded string is probably wrong. With Capicom the string looks good: "MIIEzwYJKoZIhvc....", but with CryptoApi(CryptSignMessage) it starts like "0‚'#4'ò'#6#9'*†H†÷'" How can I get to the encoded string? The code I use is as follows... procedure TForm1.Button5Click(Sender: TObject); var SigParams: CRYPT_SIGN_MESSAGE_PARA; MessageArray: pacarPByte; MessageSize: pacarDWORD; Signed_MessageBlob: String; cbSignedMessageBlob: DWord; pSignerCert: PCCERT_CONTEXT; hStoreHandle: HCERTSTORE; aStr: String; pWChar: PWideChar; sSubjStr: String; pSubjName: PWideChar; sMess: String; begin // Open a certificate store... aStr := 'my'; GetMem(pWChar,2*Length(aStr)+1); StringToWideChar(aStr,pWChar,2*Length(aStr)+1); hStoreHandle := CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, pWChar); if hStoreHandle = nil then raise Exception.Create('The "my" store could not be opened.'); // Find a certificate... sSubjStr := 'Petr'; GetMem(pSubjName,2*Length(sSubjStr)+1); StringToWideChar(sSubjStr,pSubjName,2*Length(sSubjStr)+1); pSignerCert := CertFindCertificateInStore(hStoreHandle, X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, pSubjName, nil); if pSignerCert = nil then raise Exception.Create('Signer certificate not found.'); FillChar(SigParams, sizeof(CRYPT_SIGN_MESSAGE_PARA), #0); with SigParams do begin cbSize := sizeof(CRYPT_SIGN_MESSAGE_PARA); dwMsgEncodingType := X509_ASN_ENCODING or PKCS_7_ASN_ENCODING; pSigningCert := pSignerCert; HashAlgorithm.pszObjId := szOID_RSA_MD2; // szOID_RSA_MD2 or szOID_RSA_MD5 cMsgCert := 1; rgpMsgCert := @pSignerCert; end; sMess := 'Trial message to encode.'; SetLength(MessageArray, sizeof(PByte)); SetLength(MessageSize, sizeof(DWORD)); MessageArray[0]:= @sMess[1]; MessageSize[0]:= Length(sMess); if CryptSignMessage(@SigParams,False,1,MessageArray,MessageSize,nil,@cbSignedMessageBlob) then ShowMessage(Format('CryptSignMessage first - done.'+#13#10+ 'The size of the BLOB is %d.',[cbSignedMessageBlob])) else raise Exception.Create('CryptSignMessage first - Error'); SetLength(Signed_MessageBlob, cbSignedMessageBlob); if CryptSignMessage(@SigParams,False,1,MessageArray,MessageSize,@Signed_MessageBlob[1],@cbSignedMessageBlob) then begin ShowMessage(Format('CryptSignMessage second - done'+#13#10+ 'The size of the BLOB is %d.',[cbSignedMessageBlob])); ShowMessage(Signed_MessageBlob); // ??????????????????????????????? end else raise Exception.Create('CryptSignMessage second - Error'); CertCloseStore(pSignerCert,0); end; I would be grateful if someone could help me... can be written even in russian, I hope I'll be able to cope with the language. Petr&Dickie | ||||
Ответы: | ||||
| ||||
When calling CAPICOM SignedData.Sign method you probably omit last parameter EncodingType. So, Sign produces base64 encoded data, while CryptSignMessage produces pure binary. If you pass CAPICOM_ENCODE_BINARY (1), Sign will produce binary output too. To convert it between each other you can use CAPICOM.Utilities.Base64Decode/Encode methods or any component shipped with Delphi (I believe there exist some) | ||||
| ||||
I added this code (to CryptSignMessage version): Utilities := CreateOleObject('CAPICOM.utilities'); try aStr := Utilities.Base64Encode(Signed_MessageBlob); ShowMessage(aStr); finally Utilities := Null; end; Now the encoded string starts with "MAAaIAQASA" and does not resemble (not speaking it should be the same I think) the Capicom SignedData.sign string. It is even much longer - "The size of the blob is 1270." unlike relatively short string displayed with Capicom. So where might be the bug now? | ||||
| ||||
"Bug" lies in passing parameters to Base64Encode method. This is Delphi feature afaik, type String is automatically converted to Unicode when passed as argument which requires Unicode string. And in this particular case it is done incorrectly, since original data changes. If you do Base64Decode after encoding and compare it to decoded CAPICOM output you will see that binary data is also different. However I don't know solution to this problem, since I don't know Delphi, you need to search appropriate forums or rather switch to C/C++ :) | ||||