【问题标题】:How can I create a base64url from a sha256 encoded string in C++如何从 C++ 中的 sha256 编码字符串创建 base64url
【发布时间】:2023-03-09 10:13:01
【问题描述】:

这个 C# 代码:

            string code_verifier = "xe-V-ykFyCazK3jCWwqRCZHKAKJ0MqdZs8F6xenxjFE";
            byte[] sha256verifier = sha256(code_verifier);
            string code_challenge = base64urlencodeNoPadding(sha256verifier);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < sha256verifier.Length; i++)
                builder.Append(sha256verifier[i].ToString("x2"));
            output("code_verifier: " + code_verifier);
            output("builder: " + builder.ToString());
            output("code_challenge: " + code_challenge); 

产生这些结果:

    code_verifier: xe-V-ykFyCazK3jCWwqRCZHKAKJ0MqdZs8F6xenxjFE
    builder: 8b6526951bf46153a9a276be579ee1070f86e0812fbde8b8c37a3e64c3368525
    code_challenge: i2UmlRv0YVOpona-V57hBw-G4IEvvei4w3o-ZMM2hSU

我正在尝试使用 poco 在 C++ 中做同样的事情,这是我的代码:

    std::string verifier_ = "xe-V-ykFyCazK3jCWwqRCZHKAKJ0MqdZs8F6xenxjFE";
    std::string sha256verifier = sha256(verifier_);
    std::stringstream ss;
    Poco::Base64Encoder b64enc(ss, Poco::BASE64_URL_ENCODING || Poco::BASE64_NO_PADDING);
    b64enc << sha256(sha256verifier);
    std::string challenge = ss.str();
    cout << "verifier: " << verifier_ << endl;
    cout << "sha256verifier: " << sha256verifier << endl;
    cout << "challenge: " << challenge << endl;

结果是:

verifier: xe-V-ykFyCazK3jCWwqRCZHKAKJ0MqdZs8F6xenxjFE
sha256verifier: 8b6526951bf46153a9a276be579ee1070f86e0812fbde8b8c37a3e64c3368525
challenge: YTIzY2U1YTYxY2IwMTU0ZmFhZjU1ZWY2ZDEyNGYzZjE3MjQzN2M1MTExNmRiZTY1ZDU1ZTc1NWY2ZjMyNjZi

C# sha256() 函数返回一个 32 元素字节数组,base64urlencodeNoPadding 将其转换为 32 个字符的字符串。

C++ sha256() 函数返回由 Poco::Base64Encoder 转换为与 C# 字符串无关的 64 元素字符串的相同数据的 32 元素十六进制编码字符串。

如何从 C++ 中获得与从 C# 中获得的结果相同的结果?

这是我的 poco sha256 函数

std::string::sha256(std::string buffer) {
    Poco::Crypto::RSAKey key(Poco::Crypto::RSAKey::KL_2048,
    Poco::Crypto::RSAKey::EXP_LARGE);
    Poco::Crypto::RSADigestEngine eng(key, "SHA256");
    eng.update(buffer.c_str(), buffer.size());
    const auto& sig = eng.digest(); // We just want the digest, unsigned.
    return Poco::DigestEngine::digestToHex(sig);
}

【问题讨论】:

  • 我使用了两个结果相同的 sha256 函数,zedwood.com/article/cpp-sha256-function 和 Poco::Crypto::RSADigestEngine
  • 如您所见,该函数在末尾执行return Poco::DigestEngine::digestToHex,从而向您返回一个十六进制字符串。
  • 那么我可以从中获取一个 char 数组吗?如果可以的话,我如何从中生成一个 Base64URL 编码的字符串?

标签: c++ encryption poco


【解决方案1】:

您的 C++ 解决方案中有 2 个问题:

  • 您执行 SHA-256 两次 - 在 sha256(verifier_)sha256(sha256verifier)
  • Poco::DigestEngine::digestToHex 将 SHA-256 和转换为十六进制字符串

试试这样的东西(未经测试):

std::string verifier_ = "xe-V-ykFyCazK3jCWwqRCZHKAKJ0MqdZs8F6xenxjFE";
auto sha256verifier = sha256(verifier_);
std::string challenge = toBase64(sha256verifier);
cout << "verifier: " << verifier_ << endl;
cout << "sha256verifier: " << toHex(sha256verifier) << endl;
cout << "challenge: " << challenge << endl;

std::vector<unsigned char> sha256(std::string const& buffer) {
    Poco::Crypto::RSAKey key(Poco::Crypto::RSAKey::KL_2048, Poco::Crypto::RSAKey::EXP_LARGE);
    Poco::Crypto::RSADigestEngine eng(key, "SHA256");
    eng.update(buffer.c_str(), buffer.size());
    return eng.digest();
}

std::string toBase64(std::vector<unsigned char> const& sig) {
    std::stringstream ss;
    Poco::Base64Encoder b64enc(ss, Poco::BASE64_URL_ENCODING || Poco::BASE64_NO_PADDING);
    b64enc.write((const char*)sig.data(), sig.size());
    b64enc.close();
    return ss.str();
}

std::string toHex(std::vector<unsigned char> const& sig) {
    return Poco::DigestEngine::digestToHex(sig);
}

【讨论】:

  • 顺便说一句,在简化我的帖子代码时,双重加密是一个错误
  • 我说的太早了,昨晚我只是快速尝试了一下,没有注意到编码字符串太短。 sha256 结果与 C# 相同,但 base64 编码要短三个字符。返回值是 i2UmlRv0YVOpona-V57hBw-G4IEvvei4w3o-ZMM2 并且它需要是 i2UmlRv0YVOpona-V57hBw-G4IEvvei4w3o-ZMM2hSU 谷歌才能接受它为有效。有什么想法吗?
  • 根据 Poco Base64Encoder 文档,您似乎应该关闭它。所以尝试在return ss.str();之前添加b64enc.close();
  • 我添加了 close ,现在我得到了 i2UmlRv0YVOpona-V57hBw-G4IEvvei4w3o-ZMM2hSU= 除了单个填充“=”之外它是正确的,即使没有指定填充。无论如何,我可以检查并删除任何填充。谢谢。
猜你喜欢
  • 2021-11-27
  • 2020-06-05
  • 2018-12-28
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多