@@ -240,32 +240,22 @@ internal static SafeKeychainHandle CreateOrOpenKeychain(string keychainPath, boo
240240
241241 internal static unsafe SafeTemporaryKeychainHandle CreateTemporaryKeychain ( )
242242 {
243- const int RandomSize = 256 ;
243+ // Because we use the RNG to choose from 64 items, we only get 6 bits per byte of random.
244+ // 128 * 6 is 768 bits of random, which undoubtedly vastly exceeds the space of the key
245+ // it turns into, so it's plenty.
246+ const int RandomSize = 128 ;
247+ ReadOnlySpan < byte > choices = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@"u8 ;
248+ Debug . Assert ( int . IsPow2 ( choices . Length ) , $ "Choice-set length { choices . Length } should be a power of 2 for perf") ;
244249
245250 string tempPath = Path . GetTempPath ( ) ;
246251 string tmpKeychainPath = Path . EndsInDirectorySeparator ( tempPath ) ?
247252 $ "{ tempPath } { Guid . NewGuid ( ) : N} .keychain" :
248253 $ "{ tempPath } { Path . DirectorySeparatorChar } { Guid . NewGuid ( ) : N} .keychain";
249254
250255 // Use a random password so that if a keychain is abandoned it isn't recoverable.
251- // We use stack to minimize lingering
252- Span < byte > random = stackalloc byte [ RandomSize ] ;
253- RandomNumberGenerator . Fill ( random ) ;
254-
255- // Create hex-like UTF8 string.
256- Span < byte > utf8Passphrase = stackalloc byte [ RandomSize * 2 + 1 ] ;
257- utf8Passphrase [ RandomSize * 2 ] = 0 ; // null termination for C string.
258-
259- for ( int i = 0 ; i < random . Length ; i ++ )
260- {
261- // Instead of true hexadecimal, we simply take lower and upper 4 bits and we offset them from ASCII 'A'
262- // to get printable form. We dont use managed string to avoid lingering copies.
263- utf8Passphrase [ i * 2 ] = ( byte ) ( ( random [ i ] & 0x0F ) + 65 ) ;
264- utf8Passphrase [ i * 2 + 1 ] = ( byte ) ( ( random [ i ] >> 4 ) & 0x0F + 65 ) ;
265- }
266-
267- // clear the binary bits.
268- CryptographicOperations . ZeroMemory ( random ) ;
256+ Span < byte > utf8Passphrase = stackalloc byte [ RandomSize + 1 ] ;
257+ utf8Passphrase [ RandomSize ] = 0 ; // null termination for C string.
258+ RandomNumberGenerator . GetItems ( choices , utf8Passphrase . Slice ( 0 , RandomSize ) ) ;
269259
270260 SafeTemporaryKeychainHandle keychain ;
271261 int osStatus ;
0 commit comments