Comment le Hasard est le Système.GUID.NewGuid()? (Prendre deux)
avant que vous ne marquiez ceci comme un duplicata , Lisez-moi. L'autre question a une (très probablement) mauvaise réponse acceptée.
Je ne sais pas comment .net génère ses GUIDs, probablement seulement Microsoft, mais il y a de fortes chances qu'il appelle simplement CoCreateGuid () . Cette fonction est cependant documentée pour appeler UuidCreate () . Et les algorithmes pour créer un UUID sont assez bien documenté .
pour faire court, il semble que System.Guid.NewGuid()
utilise en effet version 4 algorithme de génération UUID , parce que toutes les GUIDs qu'il correspond génère les critères (voir pour vous-même, j'ai essayé quelques millions de GUIDs, ils ont tous correspondu).
en d'autres termes, ces GUIDs sont presque aléatoire, sauf pour quelques bits connus.
cela soulève encore une fois la question-Comment aléatoire est ce aléatoire? Comme le sait tout bon petit programmeur, un algorithme de nombres pseudo-aléatoires n'est qu'aussi aléatoire que sa graine (alias entropie). Alors, quelle est la graine pour UuidCreate()
? Comment ofter est le PRNG ré-ensemencé? Est-il cryptographiquement fort, ou Puis-je m'attendre à ce que les mêmes GUIDs commencent à couler si deux ordinateurs appellent accidentellement System.Guid.NewGuid()
en même temps? Et l'état du PRNG peut-il être deviné si suffisamment de conjectures générées de façon séquentielle sont recueillies?
, a Ajouté: Pour être clair, je voudrais savoir comment aléatoire puis-je faire confiance à l'être, et donc - où puis-je l'utiliser. Donc, nous allons établir une échelle de rugosité "aléatoire" ici:
- aléatoire Basique, prenant le temps actuel comme semence. Utilisable pour mélanger des cartes en Solitaire, mais peu d'autres collisions sont trop faciles à trouver, même sans essayer.
- aléatoire plus avancé, en utilisant non seulement le temps, mais d'autres facteurs propres à la machine pour les semences. Peut-être aussi semé qu'une seule fois au démarrage du système. Cela peut être utilisé pour générer des ID dans un DB parce que les doublons sont peu probables. Pourtant, ce n'est pas bon pour la sécurité parce que les résultats peuvent être prédits avec un effort suffisant.
- Cryptograhpically aléatoire, à l'aide du bruit de l'appareil ou d'autres sources de l'aléatoire pour les semences. Re-ensemencé sur chaque invocation ou au moins assez souvent. Peut être utilisé pour les identifiants de session, distribués à des parties non fiables,etc.
je suis arrivé à cette question en pensant s'il serait correct de les utiliser comme ID DB, et si le Guid.comb l'implémentation de l'algorithme avec System.Guid.NewGuid()
(comme le fait NHibernate) serait imparfaite ou non.
9 réponses
la réponse acceptée à une question connexe se lit comme suit:
un guide ne fait pas des garanties sur l'aléatoire, il fait des garanties autour de l'unicité. Si vous voulez randomness, utilisez Random pour générer une chaîne de caractères.
toute autre chose est un détail de mise en œuvre (et pourrait changer).
mise à jour: pour clarifier mon point: même si L'implémentation actuelle de .NET 3.5 a produit un il n'y a aucune garantie que ce soit le cas à l'avenir ou vrai pour d'autres implémentations de la BCL (par ex. Mono, Silverlight, CF, etc)
mise à jour 2: le format de UUID est spécifié par RFC4122 . Section 6 , fait une déclaration explicite sur la sécurité:
ne supposez pas que les UUIDs sont difficiles à deviner; ils devraient pas être utilisé en tant que capacités de sécurité (identificateurs dont la simple possession l'accès), par exemple. Une source de nombre aléatoire prévisible exacerber la situation.
certaines personnes ont déjà laissé entendre cela, mais je tiens à le répéter car il semble y avoir une idée fausse là-bas:
l'Aléatoire et l'unicité sont orthogonaux concepts.
les données aléatoires peuvent être uniques ou redondantes, et de même les données uniques peuvent utiliser une source aléatoire ou une source déterministe (pensez à un compteur global qui est verrouillé et incrémenté pour chaque GUID jamais créé).
GUIDs étaient conçu pour être unique, pas aléatoire. Si le générateur .NET semble utiliser des entrées aléatoires, parfait. Mais ne vous y fiez pas comme une source de hasard, ni pour la cryptographie ni pour d'autres raisons (en particulier, quelle fonction de distribution vous attendez-vous à obtenir?). D'un autre côté, vous pouvez être raisonnablement sûr que les GUIDs créés par .NET, même en grands volumes, seront uniques.
les API qui produisent des octets aléatoires mais qui ne sont pas explicitement documentées pour produire des octets aléatoires cryptographiquement forts ne peuvent pas être fiables pour produire des octets aléatoires cryptographiquement forts.
si vous avez besoin d'octets aléatoires cryptographiquement forts, alors vous devez utiliser une API qui est explicitement documentée pour les produire.
public Guid CreateCryptographicallyStrongGuid() {
var rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
var data = new byte[16];
rng.GetBytes(data);
return new Guid(data);
}
ces GUIDs sont simplement 128 bits d'aléatoire cryptographique. Ils ne sont pas structurés, et ils ne sera pas entrer en collision.
Voir cet article pour certains calculs. En utilisant "la formule générale D'anniversaire", réarrangement donne
n = sqrt (- 2T * ln (p))
où n est le nombre d'éléments choisis, T est le nombre total d'éléments (2^128), et p est la probabilité cible que tous n les éléments choisis seront différents. Avec p=.99 , ce qui donne *n = 2.61532104 * 10^18*. Cela signifie que nous pouvons générer un milliard de GUIDs vraiment aléatoires par seconde dans un système pendant un milliard de secondes (32 ans), et avoir plus de 99% de chance à la fin que chacun est unique au sein du système.
la définition D'aléatoire ne se rapporte en aucune façon à la définition D'Unique à l'échelle mondiale.
qui tire deux fois à pile ou face et qui reçoit HH, HT, TH, TT sont tous aléatoires. HH est aussi aléatoire que HT.
actionnant une pièce" spéciale " deux fois et garantissant que vous obtiendrez HT ou cette unicité.
Guid sont conçus pour être au nombre de 2 sur l'échelle, c'est à dire "peut être utilisé pour générer des Identifiants dans une base de données parce que les doublons sont rare*."
quant à la sécurité, le problème n'est pas "ce n'est pas bon pour la sécurité parce que les résultats peuvent être prédits avec un effort suffisant.". Le problème est que personne ne vous donne une garantie de sécurité documentée.
Dans la pratique, selon ce commentaire et , la génération de GUID est mis en œuvre en termes d'un cryptographically secure RNG ( CryptGenRandom
). Mais cela semble être un détail de mise en œuvre non documenté. (Et je n'ai pas vérifié cela - ce sont des commentaires aléatoires sur L'Internet, prendre avec un camion chargé de sel).
(*où "improbable" signifie quelque chose comme "les chances de n'importe qui trouver une copie de GUID avant la fin de la univers sont moins que les chances de vous personnellement gagner à la loterie."Excepté les bogues d'implémentation, bien sûr.)
selon https://msdn.microsoft.com/en-us/library/bb417a2c-7a58-404f-84dd-6b494ecf0d13#id11 , depuis Windows 2000 retour en 1999,
"les bits aléatoires pour toutes les version 4 Guid intégré dans Windows sont obtenus via L'API cryptgenrandom de Windows ou l'équivalent, la même source qui est utilisé pour la génération de clés cryptographiques"
pour que je les considère cryptographiquement sûr -- au moins dans la mesure de l'122 bits d'entropie qu'ils fournissent.
Voir aussi https://stackoverflow.com/a/35384818/284704 , où will Dean a vérifié au moyen d'une étape de débogage que le CLR appelle le bon générateur aléatoire de système D'exploitation sécurisé.
ils sont aléatoires de sorte qu'il est mathématiquement prouvable que les collisions ne devraient pas se produire pendant une très longue période, de sorte que vous pouvez supposer qu'ils sont uniques à l'échelle mondiale. Cependant, ils sont pas cryptographiquement fort, car cela exigerait un véritable aléatoire, ce qui n'est pas vraiment possible dans les ordinateurs sans matériel dédié.
en se concentrant sur votre question de en utilisant des GUID comme identificateurs de ligne :
GUID sont pour les bases de données orientées vers la réplication, ou générer des lignes à l'avance avant de les ajouter à la base de données. Si vous n'avez pas besoin de directives pour résoudre un problème particulier, essayez de vous en tenir à la numérotation incrémentale. GUID complique un peu le débogage et les tests.
la méthode de peigne dans l'article que vous mentionnez semble assez grande, en fait. Je jamais réalisé, merci pour celui-là! ( p. S. la version imprimable de cet article lit beaucoup mieux )
donc si vous n'avez pas besoin de générer un GUID à l'avance, vous pouvez laisser la base de données gérer la génération de GUID pour vous. Les différences de vitesse que vous remarquerez seulement si vous commencez à ajouter 10 000 enregistrements en une seule fois, ce que vous ne devriez pas faire de toute façon, c'est ce à quoi sert l'importation en vrac.
aussi regarder Jeff sur ID vs GUID
create table #temp ([id] uniqueidentifier primary key default(newid()), [name] varchar(20))
insert into #temp (name) values ('apple')
insert into #temp (name) values ('orange')
insert into #temp (name) values ('banana')
select * from #temp
drop table #temp
id name
------------------------------------ --------------------
911B0CBD-4EED-4EB0-8488-1B2CDD915C02 banana
56CF3A80-A2DE-4949-9C9B-5F890824EA9C orange
5990B9FD-143D-41B0-89D1-957B2C57AB94 apple
j'ai lu quelque part que les chances de gagner à la loterie serait équivalente à 24 octets" GUIDs " collision. Les GUIDs standards de 16 octets offriraient beaucoup moins de risque de collision.