rsa - 如何使用 Crypto++ 创建和验证 RSA 盲签名?

标签 rsa digital-signature crypto++

我已经阅读了我所遇到的与盲签名相关的白皮书和规范,包括维基百科条目,但这些往往侧重于其背后的数学理论。

是否有使用 Crypto++ 库在 C++ 中简洁实用的 RSA 盲签名实现?

最佳答案

Is there a concise practical implementation of RSA blind signatures within c++ using the Crypto++ library?

是的。 Crypto++ wiki 有一个关于 RSA 盲签名的部分,地址为 Raw RSA | RSA Blind Signature 。下面是来自 wiki 的代码。

Crypto++ 缺少盲签名类。下面的方法遵循 Blind Signatures 中详细介绍的基本算法。 。但是,它与 Wikipedia 的不同之处在于应用了 s(s'(x)) = x 交叉检查。交叉检查出现在Chaum's original paper中。 ,但 wiki 文章中缺少它。与 Chaum 的论文和维基百科的第二个区别是,下面的代码使用 H(m) 而不是 m。这是由于Rabin in 1979 .

据我们所知,没有涵盖签名方案的标准。缺乏标准化肯定会导致互操作问题。例如,下面的代码使用 SHA256 对要签名的消息进行哈希处理,而 RSA Blind Signature Scheme for golang使用全域哈希。另请参阅Is there a standard padding/format for RSA Blind Signatures?在 Crypto.SE 上。

您可能需要先根据 Usability of padding scheme in blinded RSA signature? 应用填充函数或RSA blind signatures in practice .


#include "cryptlib.h"
#include "integer.h"
#include "nbtheory.h"
#include "osrng.h"
#include "rsa.h"
#include "sha.h"
using namespace CryptoPP;

#include <iostream>
#include <stdexcept>
using std::cout;
using std::endl;
using std::runtime_error;

int main(int argc, char* argv[])
{
    // Bob artificially small key pair
    AutoSeededRandomPool prng;
    RSA::PrivateKey privKey;

    privKey.GenerateRandomWithKeySize(prng, 64);
    RSA::PublicKey pubKey(privKey);

    // Convenience
    const Integer& n = pubKey.GetModulus();
    const Integer& e = pubKey.GetPublicExponent();
    const Integer& d = privKey.GetPrivateExponent();

    // Print params
    cout << "Pub mod: " << std::hex << pubKey.GetModulus() << endl;
    cout << "Pub exp: " << std::hex << e << endl;
    cout << "Priv mod: " << std::hex << privKey.GetModulus() << endl;
    cout << "Priv exp: " << std::hex << d << endl;

    // For sizing the hashed message buffer. This should be SHA256 size.
    const size_t SIG_SIZE = UnsignedMin(SHA256::BLOCKSIZE, n.ByteCount());

    // Scratch
    SecByteBlock buff1, buff2, buff3;

    // Alice original message to be signed by Bob
    SecByteBlock orig((const byte*)"secret", 6);
    Integer m(orig.data(), orig.size());
    cout << "Message: " << std::hex << m << endl;

    // Hash message per Rabin (1979)
    buff1.resize(SIG_SIZE);
    SHA256 hash1;
    hash1.CalculateTruncatedDigest(buff1, buff1.size(), orig, orig.size());

    // H(m) as Integer
    Integer hm(buff1.data(), buff1.size());
    cout << "H(m): " << std::hex << hm << endl;

    // Alice blinding
    Integer r;
    do {
        r.Randomize(prng, Integer::One(), n - Integer::One());
    } while (!RelativelyPrime(r, n));

    // Blinding factor
    Integer b = a_exp_b_mod_c(r, e, n);
    cout << "Random: " << std::hex << b << endl;

    // Alice blinded message
    Integer mm = a_times_b_mod_c(hm, b, n);
    cout << "Blind msg: " << std::hex << mm << endl;

    // Bob sign
    Integer ss = privKey.CalculateInverse(prng, mm);
    cout << "Blind sign: " << ss << endl;

    // Alice checks s(s'(x)) = x. This is from Chaum's paper
    Integer c = pubKey.ApplyFunction(ss);
    cout << "Check sign: " << c << endl;
    if (c != mm)
        throw runtime_error("Alice cross-check failed");

    // Alice remove blinding
    Integer s = a_times_b_mod_c(ss, r.InverseMod(n), n);
    cout << "Unblind sign: " << s << endl;

    // Eve verifies
    Integer v = pubKey.ApplyFunction(s);    
    cout << "Verify: " << std::hex << v << endl;

    // Convert to a string
    size_t req = v.MinEncodedSize();
    buff2.resize(req);
    v.Encode(&buff2[0], buff2.size());

    // Hash message per Rabin (1979)
    buff3.resize(SIG_SIZE);
    SHA256 hash2;
    hash2.CalculateTruncatedDigest(buff3, buff3.size(), orig, orig.size());

    // Constant time compare
    bool equal = buff2.size() == buff3.size() && VerifyBufsEqual(
        buff2.data(), buff3.data(), buff3.size());

    if (!equal)
        throw runtime_error("Eve verified failed");

    cout << "Verified signature" << endl;

    return 0;
}

这是构建和运行程序的结果:

$ g++ blind.cxx ./libcryptopp.a -o blind.exe
$ ./blind.exe
Pub mod: b55dc5e79993680fh
Pub exp: 11h
Priv mod: b55dc5e79993680fh
Priv exp: 1b4fc70ff2e97f1h
Message: 736563726574h
H(m): 2bb80d537b1da3e3h
Random: 72dd6819f0fc5e5fh
Blinded msg: 27a2e2e5e6f4fbfh
Blind sign: 84e7039495bf0570h
Check sign: 27a2e2e5e6f4fbfh
Unblind sign: 61054203e843f380h
Verify: 2bb80d537b1da3e3h
Verified signature

关于rsa - 如何使用 Crypto++ 创建和验证 RSA 盲签名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47860570/

相关文章:

c++ - 我们如何在 C++ 和 Windows API 中验证 openssl 数字签名

java - PGP签名格式阅读器

c++ - 使用 AES/GCM 加密的已编译 Crypto++ 库代码是否使用英特尔的 AES-NI 指令?

php异步地穴

digital-signature - 对 pdf 进行数字签名

c++ - 将十六进制字符串转换为 Crypto++ 中的字节

c++ - 在 64 位机器上进行 Crypto++ 32 位编译

c# - 在 C# 中使用私钥对数据进行签名

python - 在Python中加载RSA公钥文件并转换为二进制数组?

CryptoAPI RSA Schannel 提供程序错误