DecodingResult PKCS_EncryptionPaddingScheme::Unpad(const byte *pkcsBlock, unsigned int pkcsBlockLen, byte *output, const NameValuePairs ¶meters) const { bool invalid = false; unsigned int maxOutputLen = MaxUnpaddedLength(pkcsBlockLen); // convert from bit length to byte length if (pkcsBlockLen % 8 != 0) { invalid = (pkcsBlock[0] != 0) || invalid; pkcsBlock++; } pkcsBlockLen /= 8; // Require block type 2. invalid = (pkcsBlock[0] != 2) || invalid; // skip past the padding until we find the separator unsigned i=1; while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body } assert(i==pkcsBlockLen || pkcsBlock[i-1]==0); unsigned int outputLen = pkcsBlockLen - i; invalid = (outputLen > maxOutputLen) || invalid; if (invalid) return DecodingResult(); memcpy (output, pkcsBlock+i, outputLen); return DecodingResult(outputLen); }
DecodingResult PKCS_SignaturePaddingScheme::Unpad(const byte *pkcsBlock, unsigned int pkcsBlockLen, byte *output) const { unsigned int maxOutputLen = MaxUnpaddedLength(pkcsBlockLen); // convert from bit length to byte length if (pkcsBlockLen % 8 != 0) { if (pkcsBlock[0] != 0) return DecodingResult(); pkcsBlock++; } pkcsBlockLen /= 8; // Require block type 1. if (pkcsBlock[0] != 1) return DecodingResult(); // skip past the padding until we find the seperator unsigned i=1; while (i<pkcsBlockLen && pkcsBlock[i++]) if (pkcsBlock[i-1] != 0xff) // not valid padding return DecodingResult(); assert(i==pkcsBlockLen || pkcsBlock[i-1]==0); unsigned int outputLen = pkcsBlockLen - i; if (outputLen > maxOutputLen) return DecodingResult(); memcpy (output, pkcsBlock+i, outputLen); return DecodingResult(outputLen); }
DecodingResult OAEP_Base::Unpad(const byte *oaepBlock, size_t oaepBlockLen, byte *output, const NameValuePairs ¶meters) const { bool invalid = false; #if defined(CRYPTOPP_CXX11) std::unique_ptr<HashTransformation> pHash(NewHash()); #else std::auto_ptr<HashTransformation> pHash(NewHash()); #endif // convert from bit length to byte length if (oaepBlockLen % 8 != 0) { invalid = (oaepBlock[0] != 0) || invalid; oaepBlock++; } oaepBlockLen /= 8; const size_t hLen = pHash->DigestSize(); const size_t seedLen = hLen, dbLen = oaepBlockLen-seedLen; invalid = (oaepBlockLen < 2*hLen+1) || invalid; SecByteBlock t(oaepBlock, oaepBlockLen); byte *const maskedSeed = t; byte *const maskedDB = t+seedLen; #if defined(CRYPTOPP_CXX11) std::unique_ptr<MaskGeneratingFunction> pMGF(NewMGF()); #else std::auto_ptr<MaskGeneratingFunction> pMGF(NewMGF()); #endif pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen); pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen); ConstByteArrayParameter encodingParameters; parameters.GetValue(Name::EncodingParameters(), encodingParameters); // DB = pHash' || 00 ... || 01 || M byte *M = std::find(maskedDB+hLen, maskedDB+dbLen, 0x01); invalid = (M == maskedDB+dbLen) || invalid; invalid = (std::find_if(maskedDB+hLen, M, std::bind2nd(std::not_equal_to<byte>(), byte(0))) != M) || invalid; invalid = !pHash->VerifyDigest(maskedDB, encodingParameters.begin(), encodingParameters.size()) || invalid; if (invalid) return DecodingResult(); M++; memcpy(output, M, maskedDB+dbLen-M); return DecodingResult(maskedDB+dbLen-M); }
DecodingResult PK_FixedLengthDecryptor::Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText) const { if (cipherTextLength != FixedCiphertextLength()) return DecodingResult(); return FixedLengthDecrypt(cipherText, plainText); }
DecodingResult OAEP<H,MGF,P,PLen>::Unpad(const byte *oaepBlock, unsigned int oaepBlockLen, byte *output) const { bool invalid = false; // convert from bit length to byte length if (oaepBlockLen % 8 != 0) { invalid = (oaepBlock[0] != 0) || invalid; oaepBlock++; } oaepBlockLen /= 8; const unsigned int hLen = H::DIGESTSIZE; const unsigned int seedLen = hLen, dbLen = oaepBlockLen-seedLen; invalid = (oaepBlockLen < 2*hLen+1) || invalid; SecByteBlock t(oaepBlock, oaepBlockLen); byte *const maskedSeed = t; byte *const maskedDB = t+seedLen; H h; MGF mgf; mgf.GenerateAndMask(h, maskedSeed, seedLen, maskedDB, dbLen); mgf.GenerateAndMask(h, maskedDB, dbLen, maskedSeed, seedLen); // DB = pHash' || 00 ... || 01 || M byte *M = std::find(maskedDB+hLen, maskedDB+dbLen, 0x01); invalid = (M == maskedDB+dbLen) || invalid; invalid = (std::find_if(maskedDB+hLen, M, std::bind2nd(std::not_equal_to<byte>(), 0)) != M) || invalid; invalid = (memcmp(maskedDB, PHash<H,P,PLen>(), hLen) != 0) || invalid; if (invalid) return DecodingResult(); M++; memcpy(output, M, maskedDB+dbLen-M); return DecodingResult(maskedDB+dbLen-M); }
bool CryptoSystemValidate(PK_Decryptor &priv, PK_Encryptor &pub, bool thorough = false) { bool pass = true, fail; fail = !pub.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2) || !priv.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2); pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "cryptosystem key validation\n"; static const byte message[] = "test message"; const int messageLen = COUNTOF(message); SecByteBlock ciphertext(priv.CiphertextLength(messageLen)); SecByteBlock plaintext(priv.MaxPlaintextLength(ciphertext.size())); pub.Encrypt(GlobalRNG(), message, messageLen, ciphertext); fail = priv.Decrypt(GlobalRNG(), ciphertext, priv.CiphertextLength(messageLen), plaintext) != DecodingResult(messageLen); fail = fail || !VerifyBufsEqual(message, plaintext, messageLen); pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "encryption and decryption\n"; return pass; }