@@ -52,11 +52,9 @@ import {
52
52
checkOpts ,
53
53
clean ,
54
54
copyBytes ,
55
- type PRG ,
56
55
u32 ,
57
56
type XorStream ,
58
57
} from "./utils.ts" ;
59
- import { randomBytes } from "./webcrypto.ts" ;
60
58
61
59
// Can't use similar utils.utf8ToBytes, because it uses `TextEncoder` - not available in all envs
62
60
const _utf8ToBytes = ( str : string ) =>
@@ -116,6 +114,7 @@ const BLOCK_LEN32 = 16;
116
114
const MAX_COUNTER = 2 ** 32 - 1 ;
117
115
118
116
const U32_EMPTY = Uint32Array . of ( ) ;
117
+
119
118
function runCipher (
120
119
core : CipherCoreFn ,
121
120
sigma : Uint32Array ,
@@ -256,109 +255,3 @@ export function createCipher(core: CipherCoreFn, opts: CipherOpts): XorStream {
256
255
return output ;
257
256
} ;
258
257
}
259
-
260
- /** Internal class which wraps chacha20 or chacha8 to create CSPRNG. */
261
- export class _XorStreamPRG implements PRG {
262
- readonly blockLen : number ;
263
- readonly keyLen : number ;
264
- readonly nonceLen : number ;
265
- private state : Uint8Array ;
266
- private buf : Uint8Array ;
267
- private key : Uint8Array ;
268
- private nonce : Uint8Array ;
269
- private pos : number ;
270
- private ctr : number ;
271
- private cipher : XorStream ;
272
- constructor (
273
- cipher : XorStream ,
274
- blockLen : number ,
275
- keyLen : number ,
276
- nonceLen : number ,
277
- seed : Uint8Array ,
278
- ) {
279
- this . cipher = cipher ;
280
- this . blockLen = blockLen ;
281
- this . keyLen = keyLen ;
282
- this . nonceLen = nonceLen ;
283
- this . state = new Uint8Array ( this . keyLen + this . nonceLen ) ;
284
- this . reseed ( seed ) ;
285
- this . ctr = 0 ;
286
- this . pos = this . blockLen ;
287
- this . buf = new Uint8Array ( this . blockLen ) ;
288
- this . key = this . state . subarray ( 0 , this . keyLen ) ;
289
- this . nonce = this . state . subarray ( this . keyLen ) ;
290
- }
291
- private reseed ( seed : Uint8Array ) {
292
- abytes ( seed ) ;
293
- if ( ! seed || seed . length === 0 ) throw new Error ( "entropy required" ) ;
294
- for ( let i = 0 ; i < seed . length ; i ++ ) {
295
- this . state [ i % this . state . length ] ^= seed [ i ] ;
296
- }
297
- this . ctr = 0 ;
298
- this . pos = this . blockLen ;
299
- }
300
- addEntropy ( seed : Uint8Array ) : void {
301
- this . state . set ( this . randomBytes ( this . state . length ) ) ;
302
- this . reseed ( seed ) ;
303
- }
304
- randomBytes ( len : number ) : Uint8Array {
305
- anumber ( len ) ;
306
- if ( len === 0 ) return new Uint8Array ( 0 ) ;
307
- const out = new Uint8Array ( len ) ;
308
- let outPos = 0 ;
309
- // Leftovers
310
- if ( this . pos < this . blockLen ) {
311
- const take = Math . min ( len , this . blockLen - this . pos ) ;
312
- out . set ( this . buf . subarray ( this . pos , this . pos + take ) , 0 ) ;
313
- this . pos += take ;
314
- outPos += take ;
315
- if ( outPos === len ) return out ; // fast path
316
- }
317
- // Full blocks directly to out
318
- const blocks = Math . floor ( ( len - outPos ) / this . blockLen ) ;
319
- if ( blocks > 0 ) {
320
- const blockBytes = blocks * this . blockLen ;
321
- const b = out . subarray ( outPos , outPos + blockBytes ) ;
322
- this . cipher ( this . key , this . nonce , b , b , this . ctr ) ;
323
- this . ctr += blocks ;
324
- outPos += blockBytes ;
325
- }
326
- // Save leftovers
327
- const left = len - outPos ;
328
- if ( left > 0 ) {
329
- this . buf . fill ( 0 ) ;
330
- // NOTE: cipher will handle overflow
331
- this . cipher ( this . key , this . nonce , this . buf , this . buf , this . ctr ++ ) ;
332
- out . set ( this . buf . subarray ( 0 , left ) , outPos ) ;
333
- this . pos = left ;
334
- }
335
- return out ;
336
- }
337
- clone ( ) : _XorStreamPRG {
338
- return new _XorStreamPRG (
339
- this . cipher ,
340
- this . blockLen ,
341
- this . keyLen ,
342
- this . nonceLen ,
343
- this . randomBytes ( this . state . length ) ,
344
- ) ;
345
- }
346
- clean ( ) : void {
347
- this . pos = 0 ;
348
- this . ctr = 0 ;
349
- this . buf . fill ( 0 ) ;
350
- this . state . fill ( 0 ) ;
351
- }
352
- }
353
-
354
- export type XorPRG = ( seed ?: Uint8Array ) => _XorStreamPRG ;
355
-
356
- export const createPRG = (
357
- cipher : XorStream ,
358
- blockLen : number ,
359
- keyLen : number ,
360
- nonceLen : number ,
361
- ) : XorPRG => {
362
- return ( seed : Uint8Array = randomBytes ( 32 ) ) : _XorStreamPRG =>
363
- new _XorStreamPRG ( cipher , blockLen , keyLen , nonceLen , seed ) ;
364
- } ;
0 commit comments