实战篇-OpenSSL之HASH算法-摘要计算

本文属于《OpenSSL加密算法库使用系列教程》之一,欢迎查看其它文章。

一、HASH算法简介

Hash算法特别的地方在于它是一种单向算法,用户可以通过hash算法对目标信息生成一段特定长度的唯一hash值,却不能通过这个hash值重新获得目标信息。

因此Hash算法常用在不可还原的密码存储、信息完整性校验等。

Hash算法是不可逆的,而其他加密算法是可逆的。

比如,常见的md5,对文件计算md5,可以产生出一个128位(16字节)的散列值(hash value),用于确保文件内容的完整一致性。但是无法由md5值,解密出文件内容。

常见的Hash算法:MD2、MD4、MD5、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1、RIPEMD160

二、命令行操作

1、查看OpenSSL支持使用哪些算法,来计算摘要信息

openssl dgst -list

如下:

在这里插入图片描述

2、计算hello.txt文件的md5摘要信息

openssl dgst -md5 hello.txt

如下:

在这里插入图片描述

也可以使用支持的其他算法,来计算摘要信息,如sha1、sha256等。

三、编程实现

1、封装HASH类

封装为一个类,支持多种计算算法,如下:

HASH.h

#ifndef HASH_H
#define HASH_H

#include <QObject>
#include <QMetaEnum>
#include <QString>
#include <QByteArray>
#include <openssl/sha.h>

/**
 * @brief The HASH class
 * HASH加密算法实现类,包括Sha、Sha1、Sha224等。
 */
class HASH : public QObject
{
    Q_OBJECT

public:
    enum Mode
    {
        SHA1,
        SHA224,
        SHA256,
        SHA384,
        SHA512,
        RIPEMD160,
        MD5
    };
    Q_ENUM(Mode)

    HASH(Mode mode);

    void addData(const QByteArray &data);
    QByteArray result();

private:
    QString modeToString(Mode value);

private:
    Mode _mode;   ///<HASH算法类型
    QByteArray _data;   ///<待加密数据
};

#endif // HASH_H

HASH.cpp

#include "HASH.h"
#include <openssl/evp.h>

/**
 * @brief HASH::HASH
 * @param mode HASH算法类型
 */
HASH::HASH(Mode mode)
    :_mode(mode)
{
}

/**
 * @brief HASH::addData
 * 添加待加密数据
 * @param data 数据
 */
void HASH::addData(const QByteArray &data)
{
    _data = data;
}

/**
 * @brief HASH::result
 * 获取加密结果
 * @return 加密结果
 */
QByteArray HASH::result()
{
    OpenSSL_add_all_digests();

    const EVP_MD *md = nullptr;
    md = EVP_get_digestbyname(modeToString(_mode).toStdString().c_str());
    if(!md) // 不支持的格式
    {
        return QByteArray();
    }

    unsigned char mdValue[EVP_MAX_MD_SIZE] = {0};
    unsigned int mdLen = 0;

    EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
    EVP_MD_CTX_init(mdctx);
    EVP_DigestInit_ex(mdctx, md, nullptr);
    EVP_DigestUpdate(mdctx, _data.data(), _data.size());
    EVP_DigestFinal_ex(mdctx, mdValue, &mdLen);
    EVP_MD_CTX_free(mdctx);

    QByteArray out((const char *)mdValue, mdLen);
    return out;
}

/**
 * @brief HASH::modeToString
 * Mode型枚举值转字符串
 * @param value 枚举值
 * @return 字符串
 */
QString HASH::modeToString(HASH::Mode value)
{
    QMetaEnum metaEnum = QMetaEnum::fromType<Mode>();
    const char* key = metaEnum.valueToKey(value);
    Q_ASSERT(key != nullptr);
    return QString(key);
}

2、测试代码

void createTestData(QByteArray& data, int size)
{
    data.resize(size);
    for (int i = 0; i < size; i++)
    {
        data[i] = i % 128;
    }
}

void testHash(const QByteArray& data)
{
    // Sha1
    HASH hash1(HASH::SHA1);
    hash1.addData(data);
    qDebug() << "SHA1:" << hash1.result().toHex();

    // Sha224
    HASH hash2(HASH::SHA224);
    hash2.addData(data);
    qDebug() << "SHA224:" << hash2.result().toHex();

    // Sha256
    HASH hash3(HASH::SHA256);
    hash3.addData(data);
    qDebug() << "SHA256:" << hash3.result().toHex();

    // Sha384
    HASH hash4(HASH::SHA384);
    hash4.addData(data);
    qDebug() << "SHA384:" << hash4.result().toHex();

    // Sha512
    HASH hash5(HASH::SHA512);
    hash5.addData(data);
    qDebug() << "SHA512:" << hash5.result().toHex();

    // Ripemd160
    HASH hash6(HASH::RIPEMD160);
    hash6.addData(data);
    qDebug() << "RIPEMD160:" << hash6.result().toHex();

    // Md5
    HASH hash7(HASH::MD5);
    hash7.addData(data);
    qDebug() << "MD5:" << hash7.result().toHex();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 产生1MB+3B的测试数据,为了使该测试数据长度,不为8或16的整数倍
    QByteArray data;
    createTestData(data, 1*1024*1024+3);

    // 测试HASH
    testHash(data);

    return a.exec();
}

执行结果:

在这里插入图片描述

本文涉及工程代码地址:https://gitee.com/bailiyang/cdemo/tree/master/Qt/49OpenSSL/OpenSSL



若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

在这里插入图片描述

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百里杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值