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); }
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; }
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()); // 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 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); }
/* 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 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; }