Problem: Authentication. Project: C++ Onvif manager Deltaco camera

50 Views Asked by At

So far I have programmed login to transfer video both over the local network and over the internet. My problem now is the authenticity of the transmission of commands to the camera. With the help of ONVIF Device Manager and Wireshark, I can see how the authenticity works. The commands are sent with HTTP POST soap+xml. I have not been able to figure out how to generate "PasswordDigest" and "Base64Binery" as below.

Part if <s:Header> from ONVIF Device Manager

<UsernameToken>
    <Username>
        admin
    </Username>
    <Password
        Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">
        LgjVElh3j08Lk6p3HgMmypBjEVs=   <!-- Changes after each command -->
    </Password>
    <Nonce
        EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
        NZXdgMaDKUS7mIZNCDLydw0AAAAAAA==    <!-- Changes after each session -->
    </Nonce>
    <Created
        xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        2024-03-26T06:28:59.865Z
    </Created>
</UsernameToken>

My try with "PasswordDigest":

char _keys[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
void PasswordDigest() {
    // Password_Digest = Base64(SHA-1(nonce + created + password))

    /* Make the created */
    char buffer[30];
    struct timeval tv;
    time_t curtime;
    char created[256];
    gettimeofday(&tv, NULL);
    curtime = tv.tv_sec;
    strftime(buffer, 30, "%Y-%m-%dT%H:%M:%S.", gmtime(&curtime));
    int msec = tv.tv_usec / 1000;
    sprintf(created, "%s%03dZ", buffer, msec);
    // created = "2024-03-27T21:51:02.540Z"

    /* Make the nonce */
    uint8_t nonce[16];
    srand((int)time(NULL));
    for (int i = 0; i < 16; i++) {
        nonce[i] = 0 + (rand() % 255); // all bytes
        //int j = 0 + (rand() % sizeof(_keys));
        //nonce[i] = _keys[j];
    }
    // nonce = "3â/ߣà@‹'o½.&"

    /* Make (nonce + created + password) */
    char input[512];
    memset(input, 0, 512);
    memcpy(input, nonce, 16);
    memcpy(input + 16, created, strlen(created));
    memcpy(input + 16 + strlen(created), psw, strlen(psw));
    // input = "3â/ߣà@‹'o½.&.2024 - 03 - 27T21:51 : 02.540Zxxxxxxxxx"

    // Test with my MD5
    uint8_t hash_1[256];
    memset(hash_1, 0, 256);
    MD5(input, hash_1);
    // hash_1 = " ¡é˜jëÆÞ¸žKg/È"

    // Test with https://github.com/vog/sha1
    SHA1 checksum;
    checksum.update(input);
    const string hash_2 = checksum.final(); 
    // hash_2 = "500773ff22f6ca354763cc5ab6b7a1a0c3d62fae"

    char* output_1 = base64Encode((char*)hash_1); 
    // output_1 = "NTAwNzczZmYyMmY2Y2EzNTQ3NjNjYzVhYjZiN2ExYTBjM2Q2MmZhZQ=="

    char* output_2 = base64Encode((char*)hash_2.c_str());
    // output_2 = "NTAwNzczZmYyMmY2Y2EzNTQ3NjNjYzVhYjZiN2ExYTBjM2Q2MmZhZQ=="

    // wireshark = "LgjVElh3j08Lk6p3HgMmypBjEVs="
}

The strange thing is that hash_1 and hash_2 have different values but base64Encode generates the same value.

My try with "Base64Binary": Contrary to "PasswordDigest", I have not been able to find the prerequisites for "Base64Binary". I have tried combinations of user and password.

void Base64Binary() {

    /* Make (user + password) */
    char input[512];
    memset(input, 0, 512);
    memcpy(input, usr, strlen(usr));
    memcpy(input + strlen(usr), psw, strlen(psw));

    char* output = base64Encode(input);
    // output = "YWRtaW5lbWJsYTM0MTE="
    // wireshark = "NZXdgMaDKUS7mIZNCDLydwYAAAAAAA=="
}

Hope someone can give me a clue how to proceed. Thank you in advance.

0

There are 0 best solutions below