source: git/src-cryptopp/pssr.cpp

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 6.1 KB
Line 
1// pssr.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4#include "pssr.h"
5#include "misc.h"
6
7#include <functional>
8
9NAMESPACE_BEGIN(CryptoPP)
10
11// more in dll.cpp
12template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31;
13template<> const byte EMSA2HashId<RIPEMD128>::id = 0x32;
14template<> const byte EMSA2HashId<Whirlpool>::id = 0x37;
15
16#ifndef CRYPTOPP_IMPORTS
17
18size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
19{
20        size_t saltLen = SaltLen(digestLength);
21        size_t minPadLen = MinPadLen(digestLength);
22        return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength);
23}
24
25size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
26{
27        if (AllowRecovery())
28                return SaturatingSubtract(representativeBitLength, MinRepresentativeBitLength(hashIdentifierLength, digestLength)) / 8;
29        return 0;
30}
31
32bool PSSR_MEM_Base::IsProbabilistic() const
33{
34        return SaltLen(1) > 0;
35}
36
37bool PSSR_MEM_Base::AllowNonrecoverablePart() const
38{
39        return true;
40}
41
42bool PSSR_MEM_Base::RecoverablePartFirst() const
43{
44        return false;
45}
46
47void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng,
48        const byte *recoverableMessage, size_t recoverableMessageLength,
49        HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
50        byte *representative, size_t representativeBitLength) const
51{
52        CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(recoverableMessageLength);
53        CRYPTOPP_UNUSED(messageEmpty), CRYPTOPP_UNUSED(hashIdentifier);
54        CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
55
56        const size_t u = hashIdentifier.second + 1;
57        const size_t representativeByteLength = BitsToBytes(representativeBitLength);
58        const size_t digestSize = hash.DigestSize();
59        const size_t saltSize = SaltLen(digestSize);
60        byte *const h = representative + representativeByteLength - u - digestSize;
61
62        SecByteBlock digest(digestSize), salt(saltSize);
63        hash.Final(digest);
64        rng.GenerateBlock(salt, saltSize);
65
66        // compute H = hash of M'
67        byte c[8];
68        PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
69        PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
70        hash.Update(c, 8);
71        hash.Update(recoverableMessage, recoverableMessageLength);
72        hash.Update(digest, digestSize);
73        hash.Update(salt, saltSize);
74        hash.Final(h);
75
76        // compute representative
77        GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false);
78        byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1;
79        xorStart[0] ^= 1;
80        if (recoverableMessage && recoverableMessageLength)
81                xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength);
82        xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size());
83        if (hashIdentifier.first && hashIdentifier.second)
84        {
85                memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second);
86                representative[representativeByteLength - 1] = 0xcc;
87        }
88        else
89        {
90                representative[representativeByteLength - 1] = 0xbc;
91        }
92        if (representativeBitLength % 8 != 0)
93                representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
94}
95
96DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
97        HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
98        byte *representative, size_t representativeBitLength,
99        byte *recoverableMessage) const
100{
101        CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(messageEmpty), CRYPTOPP_UNUSED(hashIdentifier);
102        CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
103
104        const size_t u = hashIdentifier.second + 1;
105        const size_t representativeByteLength = BitsToBytes(representativeBitLength);
106        const size_t digestSize = hash.DigestSize();
107        const size_t saltSize = SaltLen(digestSize);
108        const byte *const h = representative + representativeByteLength - u - digestSize;
109
110        SecByteBlock digest(digestSize);
111        hash.Final(digest);
112
113        DecodingResult result(0);
114        bool &valid = result.isValidCoding;
115        size_t &recoverableMessageLength = result.messageLength;
116
117        valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
118
119        if (hashIdentifier.first && hashIdentifier.second)
120                valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid;
121
122        GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
123        if (representativeBitLength % 8 != 0)
124                representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
125
126        // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
127        byte *salt = representative + representativeByteLength - u - digestSize - saltSize;
128        byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), byte(0)));
129        recoverableMessageLength = salt-M-1;
130        if (*M == 0x01 &&
131           (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize) &&
132           recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize))
133        {
134                if (recoverableMessage)
135                        memcpy(recoverableMessage, M+1, recoverableMessageLength);
136        }
137        else
138        {
139                recoverableMessageLength = 0;
140                valid = false;
141        }
142
143        // verify H = hash of M'
144        byte c[8];
145        PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
146        PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
147        hash.Update(c, 8);
148        hash.Update(recoverableMessage, recoverableMessageLength);
149        hash.Update(digest, digestSize);
150        hash.Update(salt, saltSize);
151        valid = hash.Verify(h) && valid;
152
153        if (!AllowRecovery() && valid && recoverableMessageLength != 0)
154                {throw NotImplemented("PSSR_MEM: message recovery disabled");}
155
156        return result;
157}
158
159#endif
160
161NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.