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
为了什么它的价值,这是图书馆的一个非常讨厌的区域。我帮助切入了RFC 6979,确定性签名。组件之间有如此多的交互(比如消息累加器,格式化程序和签名函数),所以我把事情做得很干净整洁。对我来说这是非常痛苦的事情(当谈到Crypto ++时,我的门槛很高)。 – jww
@jww其实我试图做的是_simply_签名/验证**预计算**哈希。我不知道你是否知道[EdDSA](https://tools.ietf.org/html/rfc8032)及其变体名为PureEdDSA。然后,您可以将EdDSA简单描述为PureEdDSA对散列消息H(M)的应用。以同样的方式,我试图用“纯粹的”ECDSA签名一个预先计算的散列,我将其作为输入接收。所以我在想也许HashTransformation什么也不做,并输出消息:H(M)= M可能工作。将这种自定义HashTransformation提供给ECDSA ::签名者有可能吗? –
Lery