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