in modules/cache-material/src/caching_cryptographic_materials_decorators.ts [80:150]
export function getEncryptionMaterials<S extends SupportedAlgorithmSuites>({
buildEncryptionMaterialCacheKey,
}: CryptographicMaterialsCacheKeyHelpersInterface<S>): GetEncryptionMaterials<S> {
return async function getEncryptionMaterials(
this: CachingMaterialsManager<S>,
request: EncryptionRequest<S>
): Promise<EncryptionMaterial<S>> {
const { suite, encryptionContext, plaintextLength, commitmentPolicy } =
request
/* Check for early return (Postcondition): If I can not cache the EncryptionMaterial, do not even look. */
if (
(suite && !suite.cacheSafe) ||
typeof plaintextLength !== 'number' ||
plaintextLength < 0
) {
const material =
await this._backingMaterialsManager.getEncryptionMaterials(request)
return material
}
const cacheKey = await buildEncryptionMaterialCacheKey(this._partition, {
suite,
encryptionContext,
})
const entry = this._cache.getEncryptionMaterial(cacheKey, plaintextLength)
/* Check for early return (Postcondition): If I have a valid EncryptionMaterial, return it. */
if (entry && !this._cacheEntryHasExceededLimits(entry)) {
return cloneResponse(entry.response)
} else {
this._cache.del(cacheKey)
}
const material = await this._backingMaterialsManager
/* Strip any information about the plaintext from the backing request,
* because the resulting response may be used to encrypt multiple plaintexts.
*/
.getEncryptionMaterials({ suite, encryptionContext, commitmentPolicy })
/* Check for early return (Postcondition): If I can not cache the EncryptionMaterial, just return it. */
if (!material.suite.cacheSafe) return material
/* It is possible for an entry to exceed limits immediately.
* The simplest case is to need to encrypt more than then maxBytesEncrypted.
* In this case, I return the response to encrypt the data,
* but do not put a know invalid item into the cache.
*/
const testEntry = {
response: material,
now: Date.now(),
messagesEncrypted: 1,
bytesEncrypted: plaintextLength,
}
if (!this._cacheEntryHasExceededLimits(testEntry)) {
this._cache.putEncryptionMaterial(
cacheKey,
material,
plaintextLength,
this._maxAge
)
return cloneResponse(material)
} else {
/* Postcondition: If the material has exceeded limits it MUST NOT be cloned.
* If it is cloned, and the clone is returned,
* then there exist a copy of the unencrypted data key.
* It is true that this data would be caught by GC, it is better to just not rely on that.
*/
return material
}
}
}