void PKCS1v15_SignatureMessageEncodingMethod::ComputeMessageRepresentative(RandomNumberGenerator &rng, const byte *recoverableMessage, unsigned int recoverableMessageLength, HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, unsigned int representativeBitLength) const { unsigned int digestSize = hash.DigestSize(); if (digestSize + hashIdentifier.second + 10 > representativeBitLength/8) throw PK_Signer::KeyTooShort(); unsigned int pkcsBlockLen = representativeBitLength; // convert from bit length to byte length if (pkcsBlockLen % 8 != 0) { representative[0] = 0; representative++; } pkcsBlockLen /= 8; representative[0] = 1; // block type 1 byte *pPadding = representative + 1; byte *pDigest = representative + pkcsBlockLen - digestSize; byte *pHashId = pDigest - hashIdentifier.second; byte *pSeparator = pHashId - 1; // pad with 0xff memset(pPadding, 0xff, pSeparator-pPadding); *pSeparator = 0; memcpy(pHashId, hashIdentifier.first, hashIdentifier.second); hash.Final(pDigest); }
void PKCS1v15_SignatureMessageEncodingMethod::ComputeMessageRepresentative(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, size_t representativeBitLength) const { CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(recoverableMessageLength); CRYPTOPP_UNUSED(messageEmpty), CRYPTOPP_UNUSED(hashIdentifier); CRYPTOPP_ASSERT(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); size_t pkcsBlockLen = representativeBitLength; // convert from bit length to byte length if (pkcsBlockLen % 8 != 0) { representative[0] = 0; representative++; } pkcsBlockLen /= 8; representative[0] = 1; // block type 1 unsigned int digestSize = hash.DigestSize(); byte *pPadding = representative + 1; byte *pDigest = representative + pkcsBlockLen - digestSize; byte *pHashId = pDigest - hashIdentifier.second; byte *pSeparator = pHashId - 1; // pad with 0xff memset(pPadding, 0xff, pSeparator-pPadding); *pSeparator = 0; memcpy(pHashId, hashIdentifier.first, hashIdentifier.second); hash.Final(pDigest); }
bool HashModuleTest(HashTransformation &md, const HashTestTuple *testSet, unsigned int testSetSize) { bool pass=true, fail; SecByteBlock digest(md.DigestSize()); for (unsigned int i=0; i<testSetSize; i++) { unsigned j; for (j=0; j<testSet[i].repeatTimes; j++) md.Update(testSet[i].input, testSet[i].inputLen); md.Final(digest); fail = memcmp(digest, testSet[i].output, md.DigestSize()) != 0; pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); for (j=0; j<md.DigestSize(); j++) cout << setw(2) << setfill('0') << hex << (int)digest[j]; cout << " \"" << (char *)testSet[i].input << '\"'; if (testSet[i].repeatTimes != 1) cout << " repeated " << dec << testSet[i].repeatTimes << " times"; cout << endl; } return pass; }
bool HashModuleTest(HashTransformation &md, const HashTestTuple *testSet, unsigned int testSetSize) { bool pass=true, fail; SecByteBlock digest(md.DigestSize()); // Coverity finding (http://stackoverflow.com/a/30968371 does not squash the finding) std::ostringstream out; out.copyfmt(cout); for (unsigned int i=0; i<testSetSize; i++) { unsigned j; for (j=0; j<testSet[i].repeatTimes; j++) md.Update(testSet[i].input, testSet[i].inputLen); md.Final(digest); fail = memcmp(digest, testSet[i].output, md.DigestSize()) != 0; pass = pass && !fail; out << (fail ? "FAILED " : "passed "); for (j=0; j<md.DigestSize(); j++) out << setw(2) << setfill('0') << hex << (int)digest[j]; out << " \"" << (char *)testSet[i].input << '\"'; if (testSet[i].repeatTimes != 1) out << " repeated " << dec << testSet[i].repeatTimes << " times"; out << endl; } cout << out.str(); return pass; }
DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative( HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, size_t representativeBitLength, byte *recoverableMessage) const { assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); const size_t u = hashIdentifier.second + 1; const size_t representativeByteLength = BitsToBytes(representativeBitLength); const size_t digestSize = hash.DigestSize(); const size_t saltSize = SaltLen(digestSize); const byte *const h = representative + representativeByteLength - u - digestSize; SecByteBlock digest(digestSize); hash.Final(digest); DecodingResult result(0); bool &valid = result.isValidCoding; size_t &recoverableMessageLength = result.messageLength; valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid; valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid; GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize); if (representativeBitLength % 8 != 0) representative[0] = (byte)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)); recoverableMessageLength = salt-M-1; if (*M == 0x01 && (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize) && recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize)) { memcpy(recoverableMessage, M+1, recoverableMessageLength); } else { recoverableMessageLength = 0; valid = false; } // verify H = hash of M' byte c[8]; PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); PutWord(false, 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; }
void TestDigestOrMAC(TestData &v, bool testDigest) { std::string name = GetRequiredDatum(v, "Name"); std::string test = GetRequiredDatum(v, "Test"); member_ptr<MessageAuthenticationCode> mac; member_ptr<HashTransformation> hash; HashTransformation *pHash = NULL; TestDataNameValuePairs pairs(v); if (testDigest) { hash.reset(ObjectFactoryRegistry<HashTransformation>::Registry().CreateObject(name.c_str())); pHash = hash.get(); } else { mac.reset(ObjectFactoryRegistry<MessageAuthenticationCode>::Registry().CreateObject(name.c_str())); pHash = mac.get(); ConstByteArrayParameter iv; if (pairs.GetValue(Name::IV(), iv) && iv.size() != mac->IVSize()) SignalTestFailure(); std::string key = GetDecodedDatum(v, "Key"); mac->SetKey((const byte *)key.c_str(), key.size(), pairs); } if (test == "Verify" || test == "VerifyTruncated" || test == "NotVerify") { int digestSize = pHash->DigestSize(); if (test == "VerifyTruncated") digestSize = atoi(GetRequiredDatum(v, "TruncatedSize").c_str()); TruncatedHashModule thash(*pHash, digestSize); HashVerificationFilter verifierFilter(thash, NULL, HashVerificationFilter::HASH_AT_BEGIN); PutDecodedDatumInto(v, "Digest", verifierFilter); PutDecodedDatumInto(v, "Message", verifierFilter); verifierFilter.MessageEnd(); if (verifierFilter.GetLastResult() == (test == "NotVerify")) SignalTestFailure(); } else { SignalTestError(); assert(false); } }
/* function finalHash : This function completes the hash computation * param hashPtr : The actual hash object pointer * param input : the byte array to put the result in * param size : the length of the byte array. This will be different for different hash functions */ JNIEXPORT void JNICALL Java_edu_biu_scapi_primitives_hash_cryptopp_CryptoPpHash_finalHash (JNIEnv *env, jobject, jlong hashPtr, jbyteArray output){ HashTransformation *localHashPtr = (HashTransformation *)hashPtr; //allocate a new byte array with the size of the specific hash algorithm. byte *ret = new byte[localHashPtr->DigestSize()]; //perform the final function localHashPtr->Final(ret); //put the result of the final computation in the output array passed from java env->SetByteArrayRegion(output, 0, localHashPtr->DigestSize(), (jbyte*)ret); //make sure to release the dynamically allocated memory. Will not be deleted by the JVM. delete ret; }
void DL_SignatureMessageEncodingMethod_DSA::ComputeMessageRepresentative(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, size_t representativeBitLength) const { assert(recoverableMessageLength == 0); assert(hashIdentifier.second == 0); const size_t representativeByteLength = BitsToBytes(representativeBitLength); const size_t digestSize = hash.DigestSize(); const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize); memset(representative, 0, paddingLength); hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize)); if (digestSize*8 > representativeBitLength) { Integer h(representative, representativeByteLength); h >>= representativeByteLength*8 - representativeBitLength; h.Encode(representative, representativeByteLength); }
void EMSA2Pad::ComputeMessageRepresentative(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, size_t representativeBitLength) const { assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); if (representativeBitLength % 8 != 7) throw PK_SignatureScheme::InvalidKeyLength("EMSA2: EMSA2 requires a key length that is a multiple of 8"); size_t digestSize = hash.DigestSize(); size_t representativeByteLength = BitsToBytes(representativeBitLength); representative[0] = messageEmpty ? 0x4b : 0x6b; memset(representative+1, 0xbb, representativeByteLength-digestSize-4); // pad with 0xbb byte *afterP2 = representative+representativeByteLength-digestSize-3; afterP2[0] = 0xba; hash.Final(afterP2+1); representative[representativeByteLength-2] = *hashIdentifier.first; representative[representativeByteLength-1] = 0xcc; }
void BenchMark(const char *name, HashTransformation &ht, double timeTotal) { const int BUF_SIZE=2048U; AlignedSecByteBlock buf(BUF_SIZE); GlobalRNG().GenerateBlock(buf, BUF_SIZE); clock_t start = clock(); unsigned long i=0, blocks=1; double timeTaken; do { blocks *= 2; for (; i<blocks; i++) ht.Update(buf, BUF_SIZE); timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND; } while (timeTaken < 2.0/3*timeTotal); OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken); }
void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, size_t representativeBitLength) const { assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); const size_t u = hashIdentifier.second + 1; const size_t representativeByteLength = BitsToBytes(representativeBitLength); const size_t digestSize = hash.DigestSize(); const size_t 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]; PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); PutWord(false, 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] = (byte)Crop(representative[0], representativeBitLength % 8); }
bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative( HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, byte *representative, size_t representativeBitLength) const { SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize())); DecodingResult result = RecoverMessageFromRepresentative( hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage); return result.isValidCoding && result.messageLength == 0; }
JNIEXPORT jint JNICALL Java_edu_biu_scapi_primitives_hash_cryptopp_CryptoPpHash_getDigestSize (JNIEnv *, jobject, jlong hashPtr){ HashTransformation *localHashPtr = (HashTransformation *)hashPtr; return (jint) localHashPtr->DigestSize(); }