2017-07-19 59 views
3

我与加密+签名者玩弄和使用下面的代码,径直出了维基的预先计算哈希:签订ECDSA或DSA

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类继承的“身份”功能,我完全错过了?
如果不是,你会如何去建设类似的东西,允许指定摘要直接签名?

+0

为了什么它的价值,这是图书馆的一个非常讨厌的区域。我帮助切入了RFC 6979,确定性签名。组件之间有如此多的交互(比如消息累加器,格式化程序和签名函数),所以我把事情做得很干净整洁。对我来说这是非常痛苦的事情(当谈到Crypto ++时,我的门槛很高)。 – jww

+0

@jww其实我试图做的是_simply_签名/验证**预计算**哈希。我不知道你是否知道[EdDSA](https://tools.ietf.org/html/rfc8032)及其变体名为PureEdDSA。然后,您可以将EdDSA简单描述为PureEdDSA对散列消息H(M)的应用。以同样的方式,我试图用“纯粹的”ECDSA签名一个预先计算的散列,我将其作为输入接收。所以我在想也许HashTransformation什么也不做,并输出消息:H(M)= M可能工作。将这种自定义HashTransformation提供给ECDSA ::签名者有可能吗? – Lery

回答

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 
+0

谢谢,我会明天尝试第一件事,让你知道它是如何工作的。我对你提到的MF函数有点困惑,是指根据Sec1v2的4.1.3节将散列转换为整数的方式? – Lery

+0

精彩,它完美的工作,并与OpenSSL,mbedTLS和Go互操作!您是否以另一个HashTransformation为例?我试图从SHA3开始,但是无法围绕所有基于模板的编程打包。与我在Crypto ++代码中看到的其他散列相比,您的版本非常整齐。 – Lery

+0

绝妙的主意,谢谢。 – Lery