Explain c++ code

Hello,
i am not a c++ developer but i need to convert a short c++ script to python.
I think this code takes a checksum of a file and creates a dsa signature with a private key + this checksum or so.
Is anyone able to explain me what this c++ code does ?

Thanks guys

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <iostream>
#include <string>
#include <fstream>
#include <vector>

#include <openssl/dsa.h>
#include <openssl/sha.h>
#include <openssl/objects.h>
#include <openssl/engine.h>

// g++ dlcsign.cpp -lssl -lcrypto -o dlcsign

void readFile(
    std::vector<unsigned char> & data,
    const char * filename
) {
    data.clear();

    // open the file:
    std::streampos fileSize;
    std::ifstream file(filename, std::ios::binary);

    if (!file.is_open()) return;

    // get its size:
    file.seekg(0, std::ios::end);
    fileSize = file.tellg();
    file.seekg(0, std::ios::beg);

    // read the data:
    data.resize(fileSize);
    file.read((char*)&data[0], fileSize);
}

std::string fromHex(const std::string & hexed) {
    char h, l;
    std::string ret;
    int ie = hexed.length();
    ie -= (ie % 2 == 0) ? 1 : 2;
    for (int i = 0; i <= ie;) {
        h = hexed[i++];
        if (h >= 'A' && h <= 'F') { h = h - 'A' + 0x0a; } else
        if (h >= 'a' && h <= 'f') { h = h - 'a' + 0x0a; } else
        if (h >= '0' && h <= '9') { h -= '0'; } else {
            h = 0;
        }
        l = hexed[i++];
        if (l >= 'A' && l <= 'F') { l = l - 'A' + 0x0a; } else
        if (l >= 'a' && l <= 'f') { l = l - 'a' + 0x0a; } else
        if (l >= '0' && l <= '9') { l -= '0'; } else {
            l = 0;
        }
        ret.push_back((h << 4)|l);
    }
    return ret;
}

std::string toHex(const unsigned char * s, unsigned len, bool lower_case = false) {
    char h, l, c = lower_case ? 'a' : 'A';
    std::string ret;
    for (unsigned i = 0; i < len; ++i) {
        h = (0xf0 & s[i]) >> 4;
        if (h <= 9) { h += '0'; } else { h = h - 0x0a + c; }
        ret.push_back(h);
        l = 0x0f & s[i];
        if (l <= 9) { l += '0'; } else { l = l - 0x0a + c; }
        ret.push_back(l);
    }
    return ret;
} 

bool dlc_verify(
    const std::string & IndexFileCRC,
    const std::string & IndexFileSig
) {
    static DSA * dsa = NULL;
    if (!dsa) {
        std::vector<unsigned char> pub_key;
        readFile(pub_key, "pub.key");
        const unsigned char *p = pub_key.data();
        d2i_DSA_PUBKEY(&dsa, &p, pub_key.size());
    }
    if (!dsa) return false;

    unsigned char IndexFileCRC_sha1hash[20];
    SHA1((unsigned char*)IndexFileCRC.c_str(), IndexFileCRC.size(), IndexFileCRC_sha1hash);

    std::string IndexFileSig_bin = fromHex(IndexFileSig);
    int rc = DSA_verify(0, IndexFileCRC_sha1hash, sizeof(IndexFileCRC_sha1hash),
                        (unsigned char*) IndexFileSig_bin.c_str(), IndexFileSig_bin.size(),
                        dsa);
    return rc == 1;
}

bool dlc_sign(
    const std::string & IndexFileCRC,
    std::string & IndexFileSig
) {
    static DSA * dsa = NULL;
    if (!dsa) {
        std::vector<unsigned char> priv_key;
        readFile(priv_key, "priv.key");
        const unsigned char *p = priv_key.data();
        d2i_DSAPrivateKey(&dsa, &p, priv_key.size());
    }
    if (!dsa) return false;

    unsigned char hash[20];
    if (!SHA1((unsigned char*)IndexFileCRC.c_str(), IndexFileCRC.size(), hash)) {
        std::cerr << "ERR: SHA1 failed." << std::endl;
    } else {
        unsigned int sig_len = 0;
        unsigned char sig[256];
        if (!DSA_sign(NID_sha1, hash, sizeof(hash), sig, &sig_len, dsa)) {
            std::cerr << "ERR: DSA_sign failed." << std::endl;
        } else {
            IndexFileSig = toHex(sig, sig_len);
        }
    }
}

int main(int argc, char ** argv) {
    bool show_usage = true;
    bool do_verify = false;

    const char * pCRC = NULL;
    if (argc > 1) {
        pCRC = argv[1];
        show_usage = false;
    }
    const char * pSIGN = NULL;
    if (argc > 2) {
        pSIGN = argv[2];
        do_verify = true;
    }

    if (show_usage) {
        std::cout << "USAGE:\n    " << argv[0] << " crc signature\nEXAMPLE:\n"
        << "    dlcsign 1148974934 302c021425c3541a544de7d056b0b677810bb54d45b"
           "831ab021443163ffd73c4c34f0f2d5c7bc1778711d3a3abd4\n";
        return EXIT_SUCCESS;
    }

    if (do_verify) {
        std::cout << (dlc_verify(pCRC, pSIGN) ? ""  : "NOT " ) << "verified" << std::endl;
    } else {
        std::string sign;
        if (dlc_sign(pCRC, sign)) {
            std::cout << sign << std::endl;
        }
    }
}
Last edited on
At a guess, because I see the word sha1 in the code, its doing sha1. Which is very likely that yuo can find a python code for without the hassle of translation. can you verify this before we try to convert?

the 4 header files it #includes from openssl ... do you have this in python? This code is using a 3rd party library, not just pure c++ code.

sha1 is a bit dated, FYI. Its still nice, so long as this isnt security related code. Its fine for any other hashing usage.

it looks like some sort of digital signature, for the final output (?). Not 100% sure on that.
Its not a checksum, as best as I can tell (I don't think you can recover lost bytes like you can with a checksum?) so much as a validation / authentication tool.
Last edited on
Thanks for your reply,

you don't need to convert the script for me i can do this by my own.
I just need to understand what the c++ script is doing with the filesize and file crc32 at this point:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
bool dlc_sign(
    const std::string & IndexFileCRC,
    std::string & IndexFileSig
) {
    static DSA * dsa = NULL;
    if (!dsa) {
        std::vector<unsigned char> priv_key;
        readFile(priv_key, "priv.key");
        const unsigned char *p = priv_key.data();
        d2i_DSAPrivateKey(&dsa, &p, priv_key.size());
    }
    if (!dsa) return false;

    unsigned char hash[20];
    if (!SHA1((unsigned char*)IndexFileCRC.c_str(), IndexFileCRC.size(), hash)) {
        std::cerr << "ERR: SHA1 failed." << std::endl;
    } else {
        unsigned int sig_len = 0;
        unsigned char sig[256];
        if (!DSA_sign(NID_sha1, hash, sizeof(hash), sig, &sig_len, dsa)) {
            std::cerr << "ERR: DSA_sign failed." << std::endl;
        } else {
            IndexFileSig = toHex(sig, sig_len);
        }
    }
}


Usually, the script takes the crc32 hash of the file in hex and use this to create a dsa signature but it seems this script is a little bit diffrent.
Last edited on
IndexFileCRC.size() is not the file size, its the length of the string data that was read from the file. This is similar, I guess, to the file size, but its really just saying "for all the data, hash it"

or are you seeing something I missed with a file size? I don't see one.

as best as I can tell at a quick look it grabs all the data in the file and hashes it all as one big entity.
Last edited on
so it grabs the file data and hashes it to sha1 ?
https://www.google.com/search?q=dsa+signature+python
Is there any particular reason you can't use something which already exists?

All the heavy lifting in the code is done by library functions in -lssl and -lcrypto
It's all file handling and some eye candy in this .cpp file.

You'd be better off finding which Python bindings exist for SSL and Crypto, then writing your own Python file handling around it.

thats the first step, then it takes the hash and runs dsa on it.
Its really just a wrapper, as Salem said.
Topic archived. No new replies allowed.