使用ECDSA或DSA

时间:2017-07-19 09:38:29

标签: c++ digital-signature crypto++

我正在玩Crypto ++签名者并直接使用以下代码:

ECDSA<ECP, SHA256>::PrivateKey privateKey;
const Integer D(string("8964e19c5ae38669db3047f6b460863f5dc6c4510d3427e33545caf9527aafcf").c_str());
privateKey.Initialize(CryptoPP::ASN1::secp256r1(), D);
if (!privateKey.Validate(rng, 3)) {
    cerr << "ECDSA privateKey key validation failed after setting private parameter." << endl;
    return 1;
}

ECDSA<ECP,SHA256>::Signer signer(privateKey);
StringSource ss1(message, true,
    new SignerFilter(rng, signer,
        new HexEncoder(new StringSink(signature), false)
    ) // SignerFilter
); // StringSource
int slen = signature.length() / 2;
// since it's IEEE P1363 format to display r and s:
cout << signature.substr(0, slen) << "\n"
     << signature.substr(slen, slen) << endl;

现在,我想知道如何覆盖那里的SHA256,直接指定我想传递给签名算法的摘要值。

我已经深入研究wikidoxygen documentation,但没有成功。起初我想也许NullHash可以帮助那里,但根据来源它实际上只是零哈希。我对PK_MessageAccumulator也有一些希望,但它似乎没有像我预期的那样起作用。

那么,是否存在某种继承自HashTransformation类的“身份”功能,我完全错过了? 如果没有,你会如何建立类似的东西,允许指定直接签名的摘要?

1 个答案:

答案 0 :(得分:3)

  

H(M)=M可能有用。是否可以将此类自定义HashTransformation提供给ECDSA<ECP,H>::Signer

是。该计划如下。它提供了一个IdentityHash类,用于将输入复制到输出。它需要一个模板参数来指定散列大小。

但要小心。对消息进行哈希处理后对其进行格式化。我们真正拥有的是to_sign = MF(H(M))

$ cat test.cxx
#include "cryptlib.h"
#include "secblock.h"
#include "eccrypto.h"
#include "osrng.h"
#include "oids.h"
#include "hex.h"

#include <iostream>
#include <string>

using namespace CryptoPP;

template <unsigned int HASH_SIZE = 32>
class IdentityHash : public HashTransformation
{
public:
    CRYPTOPP_CONSTANT(DIGESTSIZE = HASH_SIZE)
    static const char * StaticAlgorithmName()
    {
        return "IdentityHash";
    }

    IdentityHash() : m_digest(HASH_SIZE), m_idx(0) {}

    virtual unsigned int DigestSize() const
    {
        return DIGESTSIZE;
    }

    virtual void Update(const byte *input, size_t length)
    {
        size_t s = STDMIN(STDMIN<size_t>(DIGESTSIZE, length),
                                         DIGESTSIZE - m_idx);    
        if (s)
            ::memcpy(&m_digest[m_idx], input, s);
        m_idx += s;
    }

    virtual void TruncatedFinal(byte *digest, size_t digestSize)
    {
        if (m_idx != DIGESTSIZE)
            throw Exception(Exception::OTHER_ERROR, "Input size must be " + IntToString(DIGESTSIZE));

        ThrowIfInvalidTruncatedSize(digestSize);

        if (digest)
            ::memcpy(digest, m_digest, digestSize);

        m_idx = 0;
    }

private:
    SecByteBlock m_digest;
    size_t m_idx;
};

int main(int argc, char* argv[])
{
    AutoSeededRandomPool prng;

    ECDSA<ECP, IdentityHash<32> >::PrivateKey privateKey;
    privateKey.Initialize(prng, ASN1::secp256r1());

    std::string message;
    message.resize(IdentityHash<32>::DIGESTSIZE);
    ::memset(&message[0], 0xAA, message.size());

    ECDSA<ECP, IdentityHash<32> >::Signer signer(privateKey);
    std::string signature;

    StringSource ss(message, true,
                        new SignerFilter(prng, signer,
                            new HexEncoder(new StringSink(signature))
                        ) // SignerFilter
                    ); // StringSource

    std::cout << "Signature: " << signature << std::endl;

    return 0;
}

我知道它会编译并生成输出。我不知道它是否是正确的输出:

skylake:cryptopp$ g++ test.cxx ./libcryptopp.a -o test.exe
skylake:cryptopp$ ./test.exe
Signature: cafb8fca487c7d5023fbc76ccf96f107f72a07fecca77254e8845a2c8f2ed0ee8b50b
8ee0702beb7572eaa30c8d250a7b082c79f2f02e58ccfb97d7091755e91

您可以使用以下内容测试IdentityHash。类IdentityHash与前一个示例没有变化。 main功能确实如此。

$ cat test.cxx
#include "cryptlib.h"
#include "secblock.h"

#include <iostream>
#include <string>

using namespace CryptoPP;

template <unsigned int HASH_SIZE = 32>
class IdentityHash : public HashTransformation
{
public:
    CRYPTOPP_CONSTANT(DIGESTSIZE = HASH_SIZE)
    static const char * StaticAlgorithmName()
    {
        return "IdentityHash";
    }

    IdentityHash() : m_digest(HASH_SIZE), m_idx(0) {}

    virtual unsigned int DigestSize() const
    {
        return DIGESTSIZE;
    }

    virtual void Update(const byte *input, size_t length)
    {
        size_t s = STDMIN(STDMIN<size_t>(DIGESTSIZE, length),
                                         DIGESTSIZE - m_idx);    
        if (s)
            ::memcpy(&m_digest[m_idx], input, s);
        m_idx += s;
    }

    virtual void TruncatedFinal(byte *digest, size_t digestSize)
    {
        if (m_idx != DIGESTSIZE)
            throw Exception(Exception::OTHER_ERROR, "Input size must be " + IntToString(DIGESTSIZE));

        ThrowIfInvalidTruncatedSize(digestSize);

        if (digest)
            ::memcpy(digest, m_digest, digestSize);

        m_idx = 0;
    }

private:
    SecByteBlock m_digest;
    size_t m_idx;
};

int main(int argc, char* argv[])
{
    std::string message;
    message.resize(IdentityHash<32>::DIGESTSIZE);
    ::memset(&message[0], 'A', message.size());

    IdentityHash<32> hash;
    hash.Update((const byte*)message.data(), message.size());

    std::string digest(32, 0);
    hash.TruncatedFinal((byte*)digest.data(), digest.size());

    std::cout << "Message: " << message << std::endl;
    std::cout << " Digest: " << digest << std::endl;

    return 0;
}

它产生:

skylake:cryptopp$ g++ test.cxx ./libcryptopp.a -o test.exe
skylake:cryptopp$ ./test.exe
Message: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 Digest: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA