Лично я бы никуда не пошел, кроме RNGCryptoServiceProvider, если кто-то не предоставит доказательство того, что он отстой.
Фактическая реализация, используемая этим классом, недоступна, потому что она реализована как часть среды выполнения (System.Security.Cryptography.Utils._GetBytes
или System.Security.Cryptography.Utils._GetNonZeroBytes
), что для меня обнадеживает, так как я надеюсь, что реализация принесет по крайней мере информацию окружения с хоста для генерации данных.
Я верю, что они перенаправляются на API-интерфейсы win32 более низкого уровня, которые, конечно, будут исправлены, если в них будет обнаружена дыра в безопасности (ну ... надеюсь!)
Как это делается в Mono, однако, я не знаю.
Для крайне параноиков
Реальная проблема с любым из этого заключается в том, что ваша случайность в .Net может быть нарушена злоумышленником, изменив поведение хоста (то есть, написав измененное время выполнения). Это намного проще в платформе в стиле VM, такой как .Net или Java, чем в собственном коде (что потребует взлома платформы нижнего уровня или изменения аппаратного обеспечения).
Любопытно, что использование RNGCryptoServiceProvider значительно облегчает эту задачу, поскольку этим вышеупомянутым внутренним вызовам неявно доверяют управляемые части инфраструктуры .Net.
Однако - на самом деле - ваш код должен быть чем-то действительно особенным, чтобы кто-то захотел приложить все эти усилия. Так что лично я все еще использовал бы RNGCryptoServiceProvider.
Но именно поэтому у меня есть реальная проблема с попытками крипто-библиотек и функций, написанных на javascript - быстрый взлом браузера может все это испортить.