small newguid net initialize conversion aleatorio c# .net security guid

newguid - string to guid conversion in c# net



Crear un GUID aleatorio criptográficamente seguro en.NET (4)

Quiero crear un GUID criptográficamente seguro (v4) en .NET.

La función Guid.NewGuid() .NET no es criptográficamente segura, pero .NET proporciona la clase System.Security.Cryptography.RNGCryptoServiceProvider .

Me gustaría poder pasar una función de número aleatorio como delegado a Guid.NewGuid (o incluso pasar alguna clase que proporciona una interfaz de generador) pero no parece que eso sea posible con la implementación predeterminada.

¿Puedo crear un GUID criptográficamente seguro utilizando System.GUID y System.Security.Cryptography.RNGCryptoServiceProvider juntos?


Sí, Guid permite crear un Guid utilizando una matriz de bytes, y RNGCryptoServiceProvider puede generar una matriz de bytes aleatorios, por lo que puede usar la salida para alimentar un nuevo Guid:

public Guid CreateCryptographicallySecureGuid() { using (var provider = new RNGCryptoServiceProvider()) { var bytes = new byte[16]; provider.GetBytes(bytes); return new Guid(bytes); } }


Si alguien está interesado aquí es el código de ejemplo anterior ajustado para .NET Core 1.0 (DNX)

public Guid CreateCryptographicallySecureGuid() { using (var provider = System.Security.Cryptography.RandomNumberGenerator.Create()) { var bytes = new byte[16]; provider.GetBytes(bytes); return new Guid(bytes); } }


Si está utilizando al menos c # 7.2 y netcoreapp2.1 (o System.Memory ), este es el enfoque más rápido / eficiente.

public static Guid CreateCryptographicallySecureGuid() { Span<byte> bytes = stackalloc byte[16]; RandomNumberGenerator.Fill(bytes); return new Guid(bytes); }

Creé una referencia comparando esto con la respuesta aceptada. Lo modifiqué para usar una implementación estática de RandomNumberGenerator ya que GetBytes() es seguro para subprocesos. (aunque la única garantía que veo es que RNGCryptoServiceProvider tiene una implementación segura para subprocesos ... es posible que otras implementaciones no lo hagan)

[MemoryDiagnoser] public class Test { private static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create(); [Benchmark] public void Heap() { var bytes = new byte[16]; _rng.GetBytes(bytes); new Guid(bytes); } [Benchmark] public void Fill() { Span<byte> bytes = stackalloc byte[16]; RandomNumberGenerator.Fill(bytes); new Guid(bytes); } }

| Method | Mean | Error | StdDev | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | |------- |---------:|----------:|----------:|------------:|------------:|------------:|--------------------:| | Heap | 129.4 ns | 0.3074 ns | 0.2725 ns | 0.0093 | - | - | 40 B | | Fill | 116.5 ns | 0.3440 ns | 0.2872 ns | - | - | - | - |


https://tools.ietf.org/html/rfc4122 dice que hay algunos bits que deben corregirse para indicar que este GUID es una versión 4 (aleatoria). Aquí está el código alterado para establecer / desarmar estos bits.

public Guid CreateCryptographicallySecureGuid() { using (var provider = new RNGCryptoServiceProvider()) { var bytes = new byte[16]; provider.GetBytes(bytes); bytes[8] = (byte)(bytes[8] & 0xBF | 0x80); bytes[7] = (byte)(bytes[7] & 0x4F | 0x40); return new Guid(bytes); } }