【问题标题】:How to create a HMAC 256 using the Crypto++ library?如何使用 Crypto++ 库创建 HMAC 256?
【发布时间】:2016-09-27 09:27:53
【问题描述】:

我有一个字符串,我需要使用 C++ 和 Crypto++ 在 HMAC 256 中进行编码。来自库wiki的代码:

AutoSeededRandomPool prng;
SecByteBlock key(16);
prng.GenerateBlock(key, key.size());

string plain = "HMAC Test";
string mac, encoded;

/*********************************\
\*********************************/

// Pretty print key
encoded.clear();
StringSource ss1(key, key.size(), true,
    new HexEncoder(
        new StringSink(encoded)
    ) // HexEncoder
); // StringSource

cout << "key: " << encoded << endl;
cout << "plain text: " << plain << endl;

/*********************************\
\*********************************/

try
{
    HMAC< SHA256 > hmac(key, key.size());

    StringSource ss2(plain, true, 
        new HashFilter(hmac,
            new StringSink(mac)
        ) // HashFilter      
    ); // StringSource
}
catch(const CryptoPP::Exception& e)
{
    cerr << e.what() << endl;
    exit(1);
}

/*********************************\
\*********************************/

// Pretty print
encoded.clear();
StringSource ss3(mac, true,
    new HexEncoder(
        new StringSink(encoded)
    ) // HexEncoder
); // StringSource

cout << "hmac: " << encoded << endl;

该示例提供了工作,但似乎做了很多。我要做的就是:

  1. 取一个字符串:“GreatWallOfChina”
  2. 键:m2hspk1ZxsjlsDU6JhMvD3TQQhm+zOwab3slKEILoSSnfk3b2+NUyeJiCrRAJ/D3V5y+QDZaIqRx9q9siMopaA==
  3. 将密钥转换为 base64:bTJoc3BrMVp4c2psc0RVNkpoTXZEM1RRUWhtK3pPd2FiM3NsS0VJTG9TU25mazNiMitOVXllSmlDclJBSi9EM1Y1eStRRFphSXFSeDlxOXNpTW9wYUE9PQ==
  4. 使用该 base64 密钥创建 hmac256。

所以,我的问题是,以上示例代码中的所有步骤都是必需的吗? (字节块声明、十六进制编码等)

抱歉,如果这是一个非常愚蠢的问题。

【问题讨论】:

  • 第 2 步是 Base64 编码的十六进制数据: 9B 68 6C A6 4D 59 C6 C8 E5 B0 35 3A 26 13 2F 0Fc74 D0 42 19 BE CC EC 1A 6F 7B 25 28 42 0B A1 24 A7 7E 4D DB DB E3 54 C9 E2 62 0A B4 40 27 F0。第 3 步 Base64 编码的第 2 步。这没有任何意义。
  • @zaph 我理解你的困惑。我应该详细说明一下。 [link]docs.gdax.com/#logon [/link] - 寻求建立与 gdax/coinbase 的修复连接。作为登录的一部分,您必须使用由消息的某些内容组成的字符串对您发送的消息进行签名。他们提供了一个 nodejs 示例,该示例似乎将提供的加密密钥转换为 base64。然后用它来生成hmac。可悲的是,这就是我的逻辑的来源。此外,他们所说的只是:“没有尾随分隔符。RawData 字段应该是 HMAC 签名的 base64 编码。”

标签: c++ cryptography hmac crypto++


【解决方案1】:

不,您的上面的步骤肯定不是必需的,例如 base 64 编码一个已经 base 64 编码的值。

Crypto++ 主要基于带有接收器和源的流式传输。这只是库的设置方式,但对于小型计算,它会有些冗长。

请注意,大多数示例代码只是简单地生成密钥并打印出明文、密钥和身份验证标签(MAC 值)以及一些异常处理。所需的代码基本上就在try / catch 块内。

【讨论】:

  • 你的答案是绝对正确的。我在下面添加了我的解决方案,这只不过是对来自 github 的 woodja 代码的微小调整。谢谢你的建议!
【解决方案2】:

那么,我的问题是,以上示例代码中的所有步骤都需要吗?

嗯,您的问题的答案大部分是肯定的。但请记住,代码是作为 wiki 的示例编写的。


您可能需要也可能不需要。但似乎您将有一个键和一个字符串要输入。

AutoSeededRandomPool prng;
SecByteBlock key(16);
prng.GenerateBlock(key, key.size());

string plain = "HMAC Test";
string mac, encoded;

如果你不是用 ASCII 打印,你可能不需要这个:

// Pretty print
encoded.clear();
StringSource ss(mac, true,
    new HexEncoder(
        new StringSink(encoded)
    ) // HexEncoder
); // StringSource

上面的代码去掉之后,剩下的就在下面了,我觉得也不过分:

try
{
    HMAC< SHA256 > hmac(key, key.size());

    StringSource ss(plain, true, 
        new HashFilter(hmac,
            new StringSink(mac)
        ) // HashFilter      
    ); // StringSource
}
catch(const CryptoPP::Exception& e)
{
    cerr << e.what() << endl;
    exit(1);
}

【讨论】:

    【解决方案3】:

    我发现其他人(woodja)在做同样的事情,但为了 aws:

    #include <iostream>
    using std::cout;
    using std::cerr;
    using std::endl;
    
    #include <string>
    using std::string;
    
    #include "cryptopp/cryptlib.h"
    using CryptoPP::Exception;
    
    #include "cryptopp/hmac.h"
    using CryptoPP::HMAC;
    
    #include "cryptopp/sha.h"
    using CryptoPP::SHA256;
    
    #include "cryptopp/base64.h"
    using CryptoPP::Base64Encoder;
    
    #include "cryptopp/filters.h"
    using CryptoPP::StringSink;
    using CryptoPP::StringSource;
    using CryptoPP::HashFilter;
    
    string sign(string key, string plain)
    {
            string mac, encoded;
            try
            {
                    HMAC< SHA256 > hmac((byte*)key.c_str(), key.length());
    
                    StringSource(plain, true,
                            new HashFilter(hmac,
                                    new StringSink(mac)
                            ) // HashFilter      
                    ); // StringSource
            }
            catch(const CryptoPP::Exception& e)
            {
                    cerr << e.what() << endl;
            }
    
            encoded.clear();
            StringSource(mac, true,
                    new Base64Encoder(
                            new StringSink(encoded)
                    ) // Base64Encoder
            ); // StringSource
            std::cout << "encode: " << encoded << endl;
            return encoded;
    }
    
    int main()
    {
            string mykey = "m2hspk1ZxsjlsDU6JhMvD3TQQhm+zOwab3slKEILoSSnfk3b2+NUyeJiCrRAJ/D3V5y+QDZaIqRx9q9siMopaA==";
            string msg = "GreatWallOfChina";
            std::cout << "key: " << mykey << std::endl;
            std::cout << "msg: " << msg << std::endl;
            sign(mykey,msg);
            return 0;
    }
    

    Github answer

    【讨论】:

    • 我讨厌分裂头发,但这不是您所提问题的答案...您似乎已经采用了 wiki 示例并输入了您的参数。
    猜你喜欢
    • 2011-11-20
    • 2018-04-29
    • 2017-12-04
    • 2022-08-17
    • 1970-01-01
    • 2022-09-27
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    相关资源
    最近更新 更多