diff --git a/.gitignore b/.gitignore index 2b30a469..8efb14a5 100644 --- a/.gitignore +++ b/.gitignore @@ -164,6 +164,7 @@ tests/rml_torture_test tests/sas_switch_torture tests/sas_torture tests/sendmail_test +tests/sha1_test tests/stringcode_test tests/tempdir_test tests/test_hash diff --git a/ChangeLog b/ChangeLog index 4b44078a..b9cf5c7b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25063,3 +25063,6 @@ 'RDConfig::provisioningServiceName()' to use the QRegularExpression class rather than QRegExp. * Added a 'provisioning_test' test harness in 'tests/'. +2025-04-29 Fred Gleason + * Cleaned up deprecation warnings in 'lib/rdhash.cpp'. + * Added a 'sha1_test' test harness in 'tests/'. diff --git a/lib/rdhash.cpp b/lib/rdhash.cpp index 736ea653..696bcb2b 100644 --- a/lib/rdhash.cpp +++ b/lib/rdhash.cpp @@ -1,8 +1,8 @@ // rdhash.cpp // -// Functions for generating hashes. +// Functions for generating and verifying hashes. // -// (C) Copyright 2017-2021 Fred Gleason +// (C) Copyright 2017-2025 Fred Gleason // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -26,6 +26,7 @@ #include #include +#include #include @@ -33,16 +34,23 @@ QString __RDSha1Hash_MakePasswordHash(const QString &secret,const QString &salt) { - SHA_CTX ctx; - unsigned char md[SHA_DIGEST_LENGTH]; + QByteArray bytes; + EVP_MD_CTX *ctx; + unsigned char *digest=NULL; + unsigned int digest_len=EVP_MD_size(EVP_sha1()); - SHA1_Init(&ctx); - SHA1_Update(&ctx,salt.toUtf8(),salt.toUtf8().length()); - SHA1_Update(&ctx,secret.toUtf8(),secret.toUtf8().length()); - SHA1_Final(md,&ctx); + ctx=EVP_MD_CTX_new(); + EVP_DigestInit_ex(ctx,EVP_sha1(),NULL); + bytes=salt.toUtf8(); + EVP_DigestUpdate(ctx,bytes,bytes.size()); + bytes=secret.toUtf8(); + EVP_DigestUpdate(ctx,bytes,bytes.size()); + digest=(unsigned char *)OPENSSL_malloc(digest_len); + EVP_DigestFinal_ex(ctx,digest,&digest_len); + EVP_MD_CTX_free(ctx); QString ret=salt; - for(int i=0;i=0) { + ctx=EVP_MD_CTX_new(); + EVP_DigestInit_ex(ctx,EVP_sha1(),NULL); + while((n=read(fd,buffer,1024))>0) { + EVP_DigestUpdate(ctx,buffer,n); + } + if(n<0) { // read() returned an error! + fprintf(stderr,"RDSha1HashFile() read error: %s\n",strerror(errno)); + } + digest=(unsigned char *)OPENSSL_malloc(digest_len); + EVP_DigestFinal_ex(ctx,digest,&digest_len); + EVP_MD_CTX_free(ctx); + QString ret; + for(unsigned i=0;i0) { - SHA1_Update(&ctx,data,n); - if(throttle) { - usleep(1); - } - } - close(fd); - SHA1_Final(md,&ctx); - ret=""; - for(int i=0;i +// (C) Copyright 2017-2025 Fred Gleason // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -21,7 +21,7 @@ #ifndef RDHASH_H #define RDHASH_H -#include +#include QString RDSha1HashData(const QByteArray &data); QString RDSha1HashFile(const QString &filename,bool throttle=false); diff --git a/tests/Makefile.am b/tests/Makefile.am index f271a8d8..10e183f3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -53,6 +53,7 @@ noinst_PROGRAMS = audio_convert_test\ reserve_carts_test\ rml_torture_test\ sendmail_test\ + sha1_test\ stringcode_test\ tempdir_test\ test_hash\ @@ -154,6 +155,10 @@ rml_torture_test_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @QT6_LIBS@ @MUSICBRAINZ_LIBS@ dist_sendmail_test_SOURCES = sendmail_test.cpp sendmail_test.h sendmail_test_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @QT6_LIBS@ @MUSICBRAINZ_LIBS@ @IMAGEMAGICK_LIBS@ +dist_sha1_test_SOURCES = sha1_test.cpp sha1_test.h +nodist_sha1_test_SOURCES = moc_sha1_test.cpp +sha1_test_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @QT6_LIBS@ @MUSICBRAINZ_LIBS@ @IMAGEMAGICK_LIBS@ + dist_stringcode_test_SOURCES = stringcode_test.cpp stringcode_test.h stringcode_test_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @QT6_LIBS@ @MUSICBRAINZ_LIBS@ @IMAGEMAGICK_LIBS@ diff --git a/tests/sha1_test.cpp b/tests/sha1_test.cpp new file mode 100644 index 00000000..f9900fe7 --- /dev/null +++ b/tests/sha1_test.cpp @@ -0,0 +1,103 @@ +// sha1_test.h +// +// Test Rivendell SHA1 methods. +// +// (C) Copyright 2025 Fred Gleason +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include +#include + +#include + +#include +#include +#include + +#include "sha1_test.h" + +MainObject::MainObject(QObject *parent) + : QObject(parent) +{ + QString verify_filename; + QString verify_password; + QString verify_string; + QString verify_hash; + + RDCmdSwitch *cmd=new RDCmdSwitch("sha1_test",SHA1_TEST_USAGE); + for(unsigned i=0;ikeys();i++) { + if(cmd->key(i)=="--verify-hash") { + verify_hash=cmd->value(i); + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--verify-filename") { + verify_filename=cmd->value(i); + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--verify-password") { + verify_password=cmd->value(i); + cmd->setProcessed(i,true); + } + if(cmd->key(i)=="--verify-string") { + verify_string=cmd->value(i); + cmd->setProcessed(i,true); + } + if(!cmd->processed(i)) { + fprintf(stderr,"sha1_test: unknown option\n"); + exit(1); + } + } + + if(!verify_password.isEmpty()) { + if(verify_hash.isEmpty()) { + QString hash=RDSha1HashPassword(verify_password); + printf("HASH: %s\n",hash.toUtf8().constData()); + printf("VERIFIED: %s\n", + RDYesNo(RDSha1HashCheckPassword(verify_password,hash)). + toUtf8().constData()); + } + else { + printf("VERIFIED: %s\n", + RDYesNo(RDSha1HashCheckPassword(verify_password,verify_hash)). + toUtf8().constData()); + } + exit(0); + } + + if(!verify_string.isEmpty()) { + printf("STRING: %s\n",verify_string.toUtf8().constData()); + printf("HASH: %s\n",RDSha1HashData(verify_string.toUtf8()). + toUtf8().constData()); + exit(0); + } + + if(!verify_filename.isEmpty()) { + printf("FILE: %s\n",verify_filename.toUtf8().constData()); + printf("HASH: %s\n",RDSha1HashFile(verify_filename.toUtf8()). + toUtf8().constData()); + exit(0); + } + + exit(0); +} + + +int main(int argc,char *argv[]) +{ + QCoreApplication a(argc,argv); + new MainObject(); + return a.exec(); +} diff --git a/tests/sha1_test.h b/tests/sha1_test.h new file mode 100644 index 00000000..45d0d44d --- /dev/null +++ b/tests/sha1_test.h @@ -0,0 +1,36 @@ +// sha1_test.h +// +// Test Rivendell SHA1 methods. +// +// (C) Copyright 2025 Fred Gleason +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef SHA1_TEST_H +#define SHA1_TEST_H + +#include + +#define SHA1_TEST_USAGE "--verify-password= --verify-string= --verify-file= --verify-hash=" + +class MainObject : public QObject +{ + Q_OBJECT + public: + MainObject(QObject *parent=0); +}; + + +#endif // SHA1_TEST_H