Generating an ONVIF authentication digest using Crypto++?

末鹿安然 提交于 2019-12-11 05:47:46

问题


The ONVIF authentication spec section 6.1.1.3 has what looks like a straight forward description of how to generate a digest. However, when using Crypto++ for Base64 and SHA1 operations, I cannot generate the same hash as the specification. I must be doing something wrong but cannot see what.

std::string nonce = "LKqI6G/AikKCQrN0zqZFlg==";
std::string dt = "2010-09-16T07:50:45Z";
std::string pwd = "userpassword";

{
    // result should be tuOSpGlFlIXsozq4HFNeeGeFLEI=
    // as per spec. This approach is also used here:
    // https://github.com/agsh/onvif/blob/master/lib/cam.js

    CryptoPP::Base64Decoder decoder;
    decoder.Put((byte*)nonce.data(), nonce.size());
    std::vector<uint8_t> bytes(decoder.MaxRetrievable(),0);
    decoder.Get(&bytes[0],bytes.size());

    //
    CryptoPP::SHA1 hash;
    byte digest[CryptoPP::SHA1::DIGESTSIZE];
    hash.Update(bytes.data(), bytes.size());
    hash.Update((const byte*)dt.c_str(), dt.size());
    hash.Update((const byte*)pwd.c_str(), pwd.size());
    hash.Final(digest);

    CryptoPP::Base64Encoder encoder;
    encoder.Put(digest, CryptoPP::SHA1::DIGESTSIZE);
    std::string hash64(encoder.MaxRetrievable(), 0);
    encoder.Get((byte*)hash64.data(), hash64.size());
    // generates woEIuU+ryXxcwkTZ9ktbKGeQ
    std::cout << hash64 << std::endl;
}

Any thoughts on this one much appreciated.

[edit: remove C# references]


回答1:


CryptoPP::Base64Decoder decoder;
decoder.Put((byte*)nonce.data(), nonce.size());
std::vector<uint8_t> bytes(decoder.MaxRetrievable(),0);
decoder.Get(&bytes[0],bytes.size());

Call MessageEnd:

Base64Decoder decoder;
decoder.Put((byte*)nonce.data(), nonce.size());
decoder.MessageEnd();

vector<uint8_t> bytes(decoder.MaxRetrievable(),0);
decoder.Get(&bytes[0],bytes.size());

Ditto:

Base64Encoder encoder;
encoder.Put(digest, 20);
encoder.MessageEnd();

string hash64(encoder.MaxRetrievable(), 0);
encoder.Get((byte*)hash64.data(), hash64.size());

Also see Base64Encoder | Missing Data and Base64Decoder | Missing Data on the Crypto++ wiki.


Nor indeed can I duplicate the result using any other approaches, like a full C# test bed using all of the .NET crypto resources.

I don't know C# as well as Crypto++, so I can't help with a C# example that works as expected with ONVIF authentication.


Here's the result I get:

$ g++ test.cxx -I. ./libcryptopp.a -o test.exe
$ ./test.exe 
tuOSpGlFlIXsozq4HFNeeGeFLEI=

And the cat test.cxx:

#include <iostream>
#include <string>
#include <vector>

#include "base64.h"
#include "sha.h"

std::string nonce = "LKqI6G/AikKCQrN0zqZFlg==";
std::string dt = "2010-09-16T07:50:45Z";
std::string pwd = "userpassword";

int main(int argc, char* argv[])
{
    CryptoPP::Base64Decoder decoder;
    decoder.Put((byte*)nonce.data(), nonce.size());
    decoder.MessageEnd();    
    std::vector<uint8_t> bytes(decoder.MaxRetrievable(),0);
    decoder.Get(&bytes[0],bytes.size());

    CryptoPP::SHA1 hash;
    byte digest[CryptoPP::SHA1::DIGESTSIZE];
    hash.Update(bytes.data(), bytes.size());
    hash.Update((const byte*)dt.c_str(), dt.size());
    hash.Update((const byte*)pwd.c_str(), pwd.size());
    hash.Final(digest);

    CryptoPP::Base64Encoder encoder;
    encoder.Put(digest, 20);
    encoder.MessageEnd();    
    std::string hash64(encoder.MaxRetrievable(), 0);
    encoder.Get((byte*)hash64.data(), hash64.size());

    std::cout << hash64 << std::endl;

    return 0;
}


来源:https://stackoverflow.com/questions/40093175/generating-an-onvif-authentication-digest-using-crypto

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!