VS 2013 , console, x64 bit project.

OpenSSL Version: 1.0.2h x64

Method for obtaining SHA1 hash:

 #include <openssl/sha.h> void SHA1::ComputeHash(std::vector<unsigned char> &buffer, std::vector<unsigned char> &result) { int i = 0; SHA_CTX sha1handler; unsigned char sha1digest[SHA_DIGEST_LENGTH] = { 0 }; auto str = std::string(buffer.begin(), buffer.end()); SHA1_Init(&sha1handler); SHA1_Update(&sha1handler, &str, str.size()); SHA1_Final(sha1digest, &sha1handler); Framework::Array::Copy(sha1digest, 0, result, 0, SHA_DIGEST_LENGTH); } 

Framework::Array::Copy method:

 void Array::Copy(unsigned char *sourceArray, int sourceIndex, std::vector<unsigned char> &destinationArray, int destinationIndex, int length) { if (destinationArray.size() == 0 || destinationArray.size() < (destinationIndex + length)) destinationArray.resize(destinationIndex + length); for (int i = sourceIndex; i < (sourceIndex + length); i++) { destinationArray[destinationIndex] = sourceArray[i]; destinationIndex++; } } 

Framework::Array::AddRange :

 void Array::AddRange(std::vector<unsigned char> &sourceArray, std::vector<unsigned char> &destinationArray, int offset, int length) { for (int i = offset; i < (offset + length); i++) destinationArray.push_back(sourceArray[i]); } 

A method in which a pointer or garbage is returned from memory instead of a value:

 void Hash(std::vector<unsigned char> &inData, std::vector<unsigned char> &salt1, std::vector<unsigned char> &salt2, int salt) { std::vector<unsigned char> buffer(20); std::vector<unsigned char> buffer2(4); std::vector<unsigned char> destinationArray(0x30); int num = 0; for (num = 0; num < 3; num++) { for (int i = 0; i <= num; i++) buffer2[i] = (salt + num); std::vector<unsigned char> localBuffer; Framework::Array::AddRange(buffer2, localBuffer, 0, (num + 1)); Framework::Array::AddRange(inData, localBuffer, 0, 0x30); Framework::Array::AddRange(salt1, localBuffer, 0, 0x20); Framework::Array::AddRange(salt2, localBuffer, 0, 0x20); SHA1::ComputeHash(localBuffer, buffer); // Вот тут в buffer возвращается указатель или мусор из памяти! } } 

The question is - why does the pointer / garbage return? If you need any more data - write in the comments. It’s not the first time that I’ve encountered something like this, the last time I failed to reproduce the problem, I hope at least this time the reason will become clear.


Update:

It was possible to find out that the pointer \ garbage is returned from OpenSSL, an example of changing the value:

1) http://i7.5cm.ru/i/kkXu.png

2) http://i7.5cm.ru/i/caXS.png

Method:

 void SHA1::ComputeHash(std::vector<unsigned char> &buffer, std::vector<unsigned char> &result) { int i = 0; SHA_CTX sha1handler; unsigned char sha1digest[SHA_DIGEST_LENGTH] = { 0 }; // Выводим HEX значение буфера printf("Buffer HEX: "); for (int i = 0; i < (int)buffer.size(); i++) printf("%X-", buffer[i]); printf("\r\n\r\n"); std::string str = std::string(buffer.begin(), buffer.end()); // Выводим длину строки printf("Str Length: %u\r\n\r\n", str.size()); // Выводим HEX значение строки printf("Str HEX: "); for (int i = 0; i < str.size(); i++) printf("%X-", str[i]); printf("\r\n\r\n"); if (!SHA1_Init(&sha1handler)) { printf("SHA1_Init == false\r\n"); // Все ок, сообщение не выводится } if (!SHA1_Update(&sha1handler, &str, str.size())) { printf("SHA1_Update == false\r\n"); // Все ок, сообщение не выводится } if (!SHA1_Final(sha1digest, &sha1handler)) { printf("SHA1_Final == false\r\n"); // Все ок, сообщение не выводится } // Выводим HEX значение результата обработки SHA1 printf("SHA1 result HEX: "); for (int i = 0; i < SHA_DIGEST_LENGTH; i++) printf("%X-", sha1digest[i]); printf("\r\n\r\n"); Framework::Array::Copy(sha1digest, 0, result, 0, SHA_DIGEST_LENGTH); } 

ps tried the older version of OpenSSL (v1.0.1t x64) - the problem is also preserved.


Test project: https://www.sendspace.com/file/japr5z

OpenSSL for Windows: https://slproweb.com/products/Win32OpenSSL.html

  • The Init, Update, and Final methods return a boolean value as a result, indicating whether the function worked correctly. What do they return to you? Or do you have them implemented differently? - isnullxbh
  • @isnullxbh, everything is fine, all functions worked fine, judging by the bullet values ​​that they returned. But the problem itself remained. Updated the method in question. - Alexis
  • Do not you think this value FFFFFFFF - suspiciously large during the withdrawal? - isnullxbh
  • @isnullxbh, remade to wstring - FF disappeared, compare values. - Alexis
  • 2
    I am confused now that all your functions are void SomeFunc () and there is no way to talk about the return value. In addition, SHA1 works with bytes, and I have strong suspicions about what you pass to the algorithm. - Vladimir Martyanov

1 answer 1

Not enough reputation for comment.

@ Vladimir Martyanov, he correctly conveys:

 BYTE == unsigned char == [0...255] 

Another thing, in what form it conveys ..

The problem is that std::wstring is passed to SHA1_Update , although it accepts a standard C-string in parameters. Recommendations:

1) Replace std::wstring with std::string .

2) Change SHA1_Update(&sha1handler, &str, str.size()) with SHA1_Update(&sha1handler, str.c_str(), str.size())

ps You still have to deal with FFFFF , wstring cuts them off, but string does not.

  • What do you think, if it only cuts - it does not solve the problem? After all, couldn’t the conclusion have such a big value? If so, the input is not valid data. - isnullxbh
  • @isnullxbh, the function deletes \ ignores invalid data (in this case, FFFFF) from std :: string, so the result is returned correct. - Alexis
  • @Alexis, but where did the wrong data come from? - isnullxbh
  • @isnullxbh, unfortunately I can’t say this, the vector with bytes is passed correctly, the constructor std::string str = std::string(buffer.begin(),buffer.end()); writes extra data std::string str = std::string(buffer.begin(),buffer.end()); Why - for me it is not clear, judging by the data from the Internet - std::string not zero terminated. Yes 0xFF far from 0x00 . - Alexis