无法使用C风格的函数调用验证签名

时间:2018-03-26 15:48:30

标签: c++ crypto++ ecdsa

以下打印失败,我无法理解原因:

#include <cryptopp/eccrypto.h>
#include <cryptopp/oids.h>
#include <cryptopp/osrng.h>
#include <iostream>
using namespace std;
using namespace CryptoPP;
int main() {
    AutoSeededRandomPool prng;
    ECDSA<ECP, SHA256>::PrivateKey private_key;
    ECDSA<ECP, SHA256>::PublicKey public_key;
    private_key.Initialize( prng, ASN1::secp160r1() );
    private_key.MakePublicKey(public_key);
    ECDSA<ECP, SHA256>::Signer signer(private_key);
    ECDSA<ECP, SHA256>::Verifier verifier(public_key);
    signer.AccessKey().Initialize(prng, ASN1::secp160r1());
    string signature(signer.MaxSignatureLength(), 0);
    string message = "asdf";
    auto signature_length = signer.SignMessage(
        prng, (const byte*)message.data(),
        message.size(), (byte*)signature.data());
    signature.resize(signature_length);
    bool verified = verifier.VerifyMessage(
        (const byte*)message.data(), message.size(),
        (const byte*)signature.data(), signature.size());
    if (verified)
        cout << "PASS" << endl;
    else
        cout << "FAIL" << endl;
}

它遵循crypto ++ wiki:https://www.cryptopp.com/wiki/ECDSA#Message_Signing中的说明,并使用从用于签署相同消息的私有派生的公钥进行验证。我应该切换到过滤器吗?

1 个答案:

答案 0 :(得分:0)

  

以下打印失败,我无法理解原因:

你很亲密。查看维基页面有一些问题。首先,这是未定义的行为(它已在维基上修复):

auto signature_length = signer.SignMessage(
    prng, (const byte*)message.data(),
    message.size(), (byte*)signature.data());

要获得非常量指针,您需要这样做(但这不是您的问题的原因):

auto signature_length = signer.SignMessage(
    prng, (const byte*)&message[0],
    message.size(), (byte*)&signature[0]);

其次,当您拨打Initialize两次时,您会敲击旧配置。 “重击”意味着您生成新参数。实际上你覆盖了另一个私钥:

private_key.Initialize( prng, ASN1::secp160r1() );
...
signer.AccessKey().Initialize(prng, ASN1::secp160r1());

不是很明显,但Initialize prng生成一个新密钥。您想要一个Initialize的{​​{1}}:

prng

第三,页面不清楚如何在Signer / Verifiers和PublicKey / PrivateKey之间移动。以下是一些其他方法可以用于说明目的:

private_key.Initialize( prng, ASN1::secp160r1() );
...
signer.AccessKey().Initialize(private_key);

我正在使用Crypto ++目录,因此包含和命令行略有不同:

cryptopp $ cat test.cxx
#include "eccrypto.h"
#include "oids.h"
#include "osrng.h"
#include <string>
#include <iostream>

int main()
{
    using namespace CryptoPP;
    AutoSeededRandomPool prng;

    ECDSA<ECP, SHA256>::Signer signer;
    ECDSA<ECP, SHA256>::Verifier verifier;

    signer.AccessKey().Initialize(prng, ASN1::secp160r1());
    signer.AccessKey().MakePublicKey(verifier.AccessKey());

    std::string signature(signer.MaxSignatureLength(), 0);
    std::string message = "asdf";

    auto signature_length = signer.SignMessage(
        prng, (const byte*)&message[0],
        message.size(), (byte*)&signature[0]);
    signature.resize(signature_length);

    bool verified = verifier.VerifyMessage(
        (const byte*)&message[0], message.size(),
        (const byte*)&signature[0], signature.size());

    if (verified)
        std::cout << "PASS" << std::endl;
    else
        std::cout << "FAIL" << std::endl;

    return 0;
}

如果您想同时使用Signer / Verifiers和PublicKey / PrivateKey,请尝试以下方法:

cryptopp$ g++ -I . test.cxx ./libcryptopp.a -o test.exe
cryptopp$ ./test.exe
PASS

这看起来有点不寻常:

cryptopp$ cat test.cxx
#include "eccrypto.h"
#include "oids.h"
#include "osrng.h"
#include <string>
#include <iostream>

int main()
{
    using namespace CryptoPP;
    AutoSeededRandomPool prng;

    ECDSA<ECP, SHA256>::Signer signer;
    ECDSA<ECP, SHA256>::Verifier verifier;

    ECDSA<ECP, SHA256>::PrivateKey& sKey = signer.AccessKey();
    sKey.Initialize(prng, ASN1::secp160r1());
    ECDSA<ECP, SHA256>::PublicKey& pKey = verifier.AccessKey();
    sKey.MakePublicKey(pKey);

    std::string signature(signer.MaxSignatureLength(), 0);
    std::string message = "asdf";

    auto signature_length = signer.SignMessage(
        prng, (const byte*)&message[0],
        message.size(), (byte*)&signature[0]);
    signature.resize(signature_length);

    bool verified = verifier.VerifyMessage(
        (const byte*)&message[0], message.size(),
        (const byte*)&signature[0], signature.size());

    if (verified)
        std::cout << "PASS" << std::endl;
    else
        std::cout << "FAIL" << std::endl;

    return 0;
}

通常您使用ECDSA<ECP, SHA256>::Signer signer; ... signer.AccessKey().Initialize(prng, ASN1::secp160r1()); {secp160r1, SHA1}。这维持了整个系统的Security Levels。当您使用{secp256k1, SHA256}时,由于{secp160r1, SHA256},您将安全级别降低到大约80位。