Bezpiecznie wygeneruj UNIQUEIDENTIFIER w SQL Server

15

Zamierzam użyć UNIQUEIDENTIFIERjako klucza dostępu, którego użytkownicy mogą używać do uzyskiwania dostępu do niektórych danych. W tym sensie klucz będzie działał jako hasło.

Muszę wygenerować wiele takich identyfikatorów jako część INSERT...SELECTinstrukcji. Ze względów architektonicznych chcę w tym przypadku wygenerować identyfikatory po stronie serwera.

Jak mogę wygenerować bezpiecznie losowy UNIQUEIDENTIFIER? Pamiętaj, że NEWIDnie byłoby to wystarczająco losowe, ponieważ w ogóle nie obiecuje żadnych właściwości bezpieczeństwa. Szukam SQL Server odpowiednika System.Security.Cryptography.RandomNumberGenerator, ponieważ potrzebuję niemożliwych do odczytania identyfikatorów. Wszystko opiera się na CHECKSUM, RANDlub GETUTCDATEnie byłoby również zakwalifikować.

usr
źródło
2
@AaronBertrand przynajmniej, jeśli cyfry są zawsze 4. Ale fakt, że nie mam mocnych dowodów na to, że można je zgadywać, nie oznacza, że ​​nie są. Nie mogę oprzeć tej decyzji bezpieczeństwa na tej obserwacji.
usr
1
Może NEWID jest tak samo losowy, jak „słabe klucze SSH Debiana”: en.wikinews.org/wiki/... Z pewnością wyglądali losowo na programistę, który je przetestował ...
usr
2
To 4 mówi ci, jakiego algorytmu używa się do generowania GUID. en.wikipedia.org/wiki/Globally_unique_identifier#Al
Algorytm
1
Rozumiesz, że jedynym czynnikiem decydującym o poziomie twojego bezpieczeństwa jest entropia bitów? Pomysł, że NEWID nie jest wystarczająco przypadkowy dla twoich potrzeb, sugerowałby, że masz pewne pojęcie o wielkości entropii bitowej, która musi być „bezpieczna” dla twojego przypadku użycia. Co to za liczba?
Cade Roux,
2
@usr - „mając pełną wiedzę o stanie wewnętrznym”, można złamać dowolne podejście.

Odpowiedzi:

26
SELECT CAST(CRYPT_GEN_RANDOM(16) AS UNIQUEIDENTIFIER)

Powinienem zrobić lewę, pomyślałbym.

CRYPT_GEN_RANDOM

Zwraca kryptograficzną liczbę losową wygenerowaną przez Crypto API (CAPI).

Martin Smith
źródło
4

Tylko moje dwa centy, ale to może nie być dobry pomysł. Parafrazując doskonałą serię Erica Lipperta na GUID ( część 1 , część 2 , część 3 ), akronimem jest GUID, a nie GSUID - globalny unikalny identyfikator, a nie globalny bezpieczny unikalny identyfikator.

Problem polega na tym, że gdy identyfikatory GUID są generowane w nieprzyjaznym zakresie, takim jak wszyscy używający NEWID (), wszystkie wartości wydają się być unikalne (cóż, w pewnym sensie, zobacz artykuł Erica, część 3). Ale jeśli wrogi byt wejdzie w ten zakres, mogą zarówno przewidzieć kolejny wygenerowany identyfikator GUID, jak i samodzielnie powodować kolizje.

Tworząc własną metodę generowania wartości przechowywanej w strukturze, która wygląda jak identyfikator GUID, zasadniczo stałeś się wrogim bytem. Zmieniłeś umowę GUID z unikalnego na losowy . Chociaż ktoś lepszy w matematyce niż ja mógłbym prawdopodobnie udowodnić, że wciąż jesteś wyjątkowy, to tylko w ramach metody twojej generacji. Jeśli połączysz te pseudo-GUID z GUID NEWID (), wszystkie zakłady są wyłączone.

Mówię, że to może nie być dobry pomysł tylko dlatego, że nie znam całego zakresu, w jaki używasz wartości. Jeśli jesteś jedyną jednostką generującą wartości (bez mieszania i dopasowywania) i / lub nie utrwalasz wartości i / lub nie przejmujesz się kolizjami, może to nie stanowić problemu. Jeśli którykolwiek z tych elementów jest nieprawdziwy, możesz dokonać ponownej oceny.

Dave Simione
źródło
Ciekawe punkty Mój wybór typu danych UNIQUEIDENTIFIERto w większości przypadek. Po prostu wygodnie jest obsłużyć 16 bajtów przy użyciu tego typu. Myślę o tym jak o haśle. Jednak musi być wyjątkowy. Jestem pewien, że nigdy nie zobaczę kolizji (a nawet jeśli aplikacja się zawiesi - to też jest bezpieczne).
usr
Nie zgadzam się, zależy to od tego, w jaki sposób go zaszyfrujesz, jeśli stanie się losowy, a nie niepowtarzalny. Może być łatwo taki sam.
Dawesi
4

Według https://blogs.msdn.microsoft.com/sqlprogrammability/2006/03/23/newsequentialid-histrorybenefits-and-implementation/ , funkcja NEWID () po prostu otacza funkcję Windows CoCreateGuid, która zwraca identyfikator GUID w stylu v4 . I zgodnie z https://msdn.microsoft.com/en-us/library/bb417a2c-7a58-404f-84dd-6b494ecf0d13#id11 , od Windows 2000 w 1999 roku,

„losowe bity dla wszystkich identyfikatorów GUID wersji 4 wbudowanych w Windows są uzyskiwane za pomocą kryptograficznego interfejsu API Windows CryptGenRandom lub równoważnego, tego samego źródła, które jest używane do generowania kluczy kryptograficznych”

Powiedziałbym więc, że można uznać NEWID () za kryptograficznie bezpieczny - przynajmniej w zakresie 122 bitów entropii, które zapewnia.

Jordan Rieger
źródło
To interesujące. Osobiście nie ufałbym temu ze względów bezpieczeństwa. Ani Windows, ani SQL Server nie dają na to gwarancji.
usr
@usr Nie jestem pewien, jak wyglądałaby gwarancja. Nie używa słowa „gwarancja”, ale wydaje się, że jest to standardowa dokumentacja MSDN Windows SDK. Jest bardzo mało prawdopodobne, aby MS obniżyło losowość kryptograficzną identyfikatorów GUID w niektórych przyszłych wersjach systemu Windows. Nic by nie zyskało.
Jordan Rieger
Ta strona MSDN jedynie dokumentuje historyczne wybory, ale nie mówi, że zostanie to zachowane w przyszłości. To samo dotyczy SQL Server. Nie mogę sobie wyobrazić okoliczności, w których to się załamałoby. Ale było wiele katastrofalnych awarii RNG. Takie założenia często okazały się fałszywe. To heurystyczny argument.
usr
@usr Ale w jaki sposób dokumentacja MSDN może zagwarantować przyszłe zachowanie systemu Windows? W tych przypadkach możemy jedynie mieć nadzieję na dokumentację obecnego zachowania. Jeśli zachowanie kiedykolwiek się zmieni, to aktualizują dokumentację. Właśnie dlatego te pytania i odpowiedzi dotyczące przepełnienia stosu mają tagi wersji i od czasu do czasu są aktualizowane.
Jordan Rieger
Gwarantują rzeczy, których nie zmienią. Mogliby zmienić produkt, ale nie zrobią tego, jeśli powiedzą: „tutaj jest kluczowa funkcja bezpieczeństwa z tymi właściwościami”. Interpretuję tę dokumentację bardziej jako pogląd historyczny niż stwierdzenie o przyszłości.
usr