How to create Password Digest for ONVIF in C++?

Viewed 28

Following ONVIF documentation, the password digest for making ONVIF Soap request should be like this.

PasswordDigest = B64ENCODE( SHA1( B64DECODE( Nonce ) + Date + Password ) )

For example:

Nonce – LKqI6G/AikKCQrN0zqZFlg==

Date – 2010-09-16T07:50:45Z

Password – userpassword

Resulting Digest – tuOSpGlFlIXsozq4HFNeeGeFLEI=

Below is how I have written in C++, which resulted in an invalid user token.

std::string dateTime = "2022-09-10T10:10:59.000Z";
std::string nonce = "secret";
std::string password = "mypassword";
std::string str =  decode_str(nonce) + dateTime + password;
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *) str.c_str(), strlen(str.c_str()) - 1, hash);
uint8_t * hash_ptr = hash;
std::string psswrd = encode_str(hash_ptr, sizeof(hash));

std::cout << psswrd << std::endl; // +cz8/SJS89Uee7cTjW9aiMG9CTE=

But the above password is invalid, resulted the request to fail after timeout.

How to create Password Digest for ONVIF in C++?

2 Answers

I believe your problem is in the call to SHA1. The second parameter (length of the string to be hashed) is strlen(str) - 1, meaning you cut off the final character of the password, which will then result in an invalid hash.

Please either use the length function of std::string or strlen without that decrement (which does not include the \0).

The second 'problem' is in the string nonce, which is not a Base64 string at all, however I am willing to assume this to be a plain 'example value' because you do not wish you disclose your actual nonce value.

Below is a valid digest password.

std::string dateTime = "2022-09-10T10:10:59.000Z";
std::string nonce = "secret";
std::string password = "mypassword";
std::string str = nonce + dateTime + password;
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *) str.c_str(), str.size(), hash);
uint8_t * hash_ptr = hash;
std::string psswrd = encode_str(hash_ptr, sizeof(hash));
Related