summaryrefslogtreecommitdiff
path: root/pssr.cpp
diff options
context:
space:
mode:
authorweidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0>2003-03-20 01:24:12 +0000
committerweidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0>2003-03-20 01:24:12 +0000
commitd23a489940499bd6c634a1cb0a9875f094f8a850 (patch)
treef85b3bed971083e90e5f3dbb84539ea4ba0359e9 /pssr.cpp
parentb3517523a738277cfe22428bd757833e69abb66e (diff)
downloadcryptopp-d23a489940499bd6c634a1cb0a9875f094f8a850.tar.gz
various changes for 5.1
git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@38 57ff6487-cd31-0410-9ec3-f628ee90f5f0
Diffstat (limited to 'pssr.cpp')
-rw-r--r--pssr.cpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/pssr.cpp b/pssr.cpp
new file mode 100644
index 0000000..020cb98
--- /dev/null
+++ b/pssr.cpp
@@ -0,0 +1,126 @@
+// pssr.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "pssr.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template<> const byte EMSA2HashId<SHA>::id = 0x33;
+template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31;
+
+unsigned int PSSR_MEM_Base::MaxRecoverableLength(unsigned int representativeBitLength, unsigned int hashIdentifierLength, unsigned int digestLength) const
+{
+ if (AllowRecovery())
+ {
+ unsigned int saltLen = SaltLen(digestLength);
+ unsigned int minPadLen = MinPadLen(digestLength);
+ return SaturatingSubtract(representativeBitLength, 8*(minPadLen + saltLen + digestLength + hashIdentifierLength) + 9) / 8;
+ }
+ return 0;
+}
+
+bool PSSR_MEM_Base::IsProbabilistic() const
+{
+ return SaltLen(1) > 0;
+}
+
+bool PSSR_MEM_Base::AllowNonrecoverablePart() const
+{
+ return true;
+}
+
+bool PSSR_MEM_Base::RecoverablePartFirst() const
+{
+ return false;
+}
+
+void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, unsigned int recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, unsigned int representativeBitLength) const
+{
+ const unsigned int u = hashIdentifier.second + 1;
+ const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
+ const unsigned int digestSize = hash.DigestSize();
+ const unsigned int saltSize = SaltLen(digestSize);
+ byte *const h = representative + representativeByteLength - u - digestSize;
+
+ SecByteBlock digest(digestSize), salt(saltSize);
+ hash.Final(digest);
+ rng.GenerateBlock(salt, saltSize);
+
+ // compute H = hash of M'
+ byte c[8];
+ UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
+ UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
+ hash.Update(c, 8);
+ hash.Update(recoverableMessage, recoverableMessageLength);
+ hash.Update(digest, digestSize);
+ hash.Update(salt, saltSize);
+ hash.Final(h);
+
+ // compute representative
+ GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false);
+ byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1;
+ xorStart[0] ^= 1;
+ xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength);
+ xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size());
+ memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second);
+ representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc;
+ if (representativeBitLength % 8 != 0)
+ representative[0] = Crop(representative[0], representativeBitLength % 8);
+}
+
+DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, unsigned int representativeBitLength,
+ byte *recoverableMessage) const
+{
+ const unsigned int u = hashIdentifier.second + 1;
+ const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
+ const unsigned int digestSize = hash.DigestSize();
+ const unsigned int saltSize = SaltLen(digestSize);
+ const byte *const h = representative + representativeByteLength - u - digestSize;
+
+ SecByteBlock digest(digestSize);
+ hash.Final(digest);
+
+ DecodingResult result(0);
+ bool &valid = result.isValidCoding;
+ unsigned int &recoverableMessageLength = result.messageLength;
+
+ valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
+ valid = (memcmp(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) == 0) && valid;
+
+ GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
+ if (representativeBitLength % 8 != 0)
+ representative[0] = Crop(representative[0], representativeBitLength % 8);
+
+ // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
+ byte *salt = representative + representativeByteLength - u - digestSize - saltSize;
+ byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), 0));
+ if (*M == 0x01 && M - representative - (representativeBitLength % 8 != 0) >= MinPadLen(digestSize))
+ {
+ recoverableMessageLength = salt-M-1;
+ memcpy(recoverableMessage, M+1, recoverableMessageLength);
+ }
+ else
+ valid = false;
+
+ // verify H = hash of M'
+ byte c[8];
+ UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
+ UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
+ hash.Update(c, 8);
+ hash.Update(recoverableMessage, recoverableMessageLength);
+ hash.Update(digest, digestSize);
+ hash.Update(salt, saltSize);
+ valid = hash.Verify(h) && valid;
+
+ if (!AllowRecovery() && valid && recoverableMessageLength != 0)
+ {throw NotImplemented("PSSR_MEM: message recovery disabled");}
+
+ return result;
+}
+
+NAMESPACE_END