Вычислить SHA1 ha sh как Git с помощью Qt C ++ - PullRequest
0 голосов
/ 12 июля 2020

Я хотел бы иметь sh файл так же, как git hash-object, поэтому я могу сравнить его с существующим ha sh, но с использованием Qt и C ++.

ответы на этот вопрос показывают, как получить такую ​​же ha sh, но ни один из примеров не использует C ++.

Пока что это то, что мы пробовали:

QString fileName = entry.toObject().value( "name" ).toString();
QByteArray shaJson = entry.toObject().value( "sha" ).toString().toUtf8();
QByteArray shaFile;

QFile f( QString( "%1/%2" ).arg( QCoreApplication::applicationDirPath() ).arg( fileName ) );
if( f.open(QFile::ReadOnly ) )
{
QCryptographicHash hash(QCryptographicHash::Sha1);
hash.addData( QString( "blob " ).toUtf8() ); // start with the string "blob "
hash.addData( QString( "%1" ).arg( f.size() ).toUtf8() ); // add size in bytes of the content
hash.addData( QString( "\0" ).toUtf8() ); // null byte
hash.addData( f.readAll() ); // actual file content
shaFile = hash.result().toHex();
if( shaFile != shaJson ){

}
}

Как реализовать этот метод хеширования с Qt?

Изменить:

Вот пример: ha sh вывод: ccbf4f0a52fd5ac59e18448ebadf2ef37c62f54f Вычислено с помощью git hash-object из этого файла: https://raw.githubusercontent.com/ilia3101/MLV-App/master/pixel_maps/80000301_1808x1007.fpm Итак, это ха sh, которое нам также нравится вычислять с помощью Qt.

1 Ответ

2 голосов
/ 12 июля 2020

Проблема в том, что, с одной стороны, QString игнорирует \0 как строку завершения, с другой стороны, QByteArray всегда добавляет дополнительные \0. Из документации Qt:

Использование QByteArray намного удобнее, чем использование const char *. За кулисами он всегда гарантирует, что за данными следует терминатор \0, и использует неявное совместное использование (копирование при записи), чтобы уменьшить использование памяти и избежать ненужного копирования данных.

https://doc.qt.io/qt-5/qbytearray.html

Итак, каждый addData в вашем случае добавляет дополнительный \0 к данным, которые должны быть хешированы. Некоторым обходным решением может быть следующий код:

QFile file(path);
if( file.open(QFile::ReadOnly ) )
{
    QCryptographicHash hash(QCryptographicHash::Sha1);
    QByteArray header = QString("blob %1").arg(file.size()).toUtf8();
    hash.addData(header.data(), header.size() + 1);
    hash.addData(file.readAll());

    shaFile = hash.result().toHex();
    qDebug() << shaFile;
}

data() из QByteArray - это , возвращающий указатель на данные, хранящиеся в массиве байтов. Указатель можно использовать для доступа и изменения байтов, составляющих массив. Данные заканчиваются символом '\ 0', т.е. количество байтов в возвращаемой символьной строке равно size () + 1 для терминатора '\ 0'. Следовательно, нам не нужно явно добавлять \0, QByteArray делает это за нас. Нам нужно добавить +1 к размеру, поскольку QByteArray возвращает размер массива, поскольку это не будет символ \0.

Приведенный выше код сгенерировал ccbf4f0a52fd5ac59e18448ebadf2ef37c62f54f для вашего файла, поэтому я предполагаю, что это это правильный га sh.

...