MCPcopy Index your code
hub / github.com/ether/etherpad / _deriveSecrets

Method _deriveSecrets

src/node/security/SecretRotator.ts:130–166  ·  view source on GitHub ↗
(p: any, now: number)

Source from the content-addressed store, hash-verified

128 }
129
130 async _deriveSecrets(p: any, now: number) {
131 this._logger.debug('deriving secrets from', p);
132 if (!p.interval) return [await algorithms[p.algId].derive(p.algParams, null)];
133 const t0 = intervalStart(now, p.interval);
134 // Start of the first interval covered by these params. To accommodate clock skew, p.interval is
135 // subtracted. If we did not do this, then the following could happen:
136 // 1. Instance (A) starts up and publishes params starting at the current interval.
137 // 2. Instance (B) starts up with a clock that is in the previous interval.
138 // 3. Instance (B) reads the params published by instance (A) and sees that there's no
139 // coverage of what it thinks is the current interval.
140 // 4. Instance (B) generates and publishes new params that covers what it thinks is the
141 // current interval.
142 // 5. Instance (B) starts generating MACs from a secret derived from the new params.
143 // 6. Instance (A) fails to validate the MACs generated by instance (B) until it re-reads
144 // the published params, which might take as long as interval.
145 // An alternative approach is to backdate p.start by p.interval when creating new params, but
146 // this could affect the end time of legacy secrets.
147 const tA = intervalStart(p.start - p.interval, p.interval);
148 const tZ = intervalStart(p.end - 1, p.interval);
149 this._logger.debug('now:', now, 't0:', t0, 'tA:', tA, 'tZ:', tZ);
150 // Starts of intervals to derive keys for.
151 const tNs = [];
152 // Whether the derived secret for the interval starting at tN is still relevant. If there was no
153 // clock skew, a derived secret is relevant until p.lifetime has elapsed since the end of the
154 // interval. To accommodate clock skew, this end time is extended by p.interval.
155 const expired = (tN:number) => now >= tN + (2 * p.interval) + p.lifetime;
156 // Walk from t0 back until either the start of coverage or the derived secret is expired. t0
157 // must always be the first entry in case p is the current params. (The first derived secret is
158 // used for generating MACs, so the secret derived for t0 must be before the secrets derived for
159 // other times.)
160 for (let tN = Math.min(t0, tZ); tN >= tA && !expired(tN); tN -= p.interval) tNs.push(tN);
161 // Include a future derived secret to accommodate clock skew.
162 if (t0 + p.interval <= tZ) tNs.push(t0 + p.interval);
163 this._logger.debug('deriving secrets for intervals with start times:', tNs);
164 return await Promise.all(
165 tNs.map(async (tN) => await algorithms[p.algId].derive(p.algParams, `${tN}`)));
166 }
167
168 async _update() {
169 const now = this._t.now();

Callers 1

_updateMethod · 0.95

Calls 4

pushMethod · 0.80
mapMethod · 0.80
intervalStartFunction · 0.70
deriveMethod · 0.45

Tested by

no test coverage detected