Gere com segurança um UNIQUEIDENTIFIER no SQL Server

15

Pretendo usar um UNIQUEIDENTIFIERcomo uma chave de acesso que os usuários possam usar para acessar determinados dados. A chave atuará como uma senha nesse sentido.

Preciso gerar vários identificadores como parte de uma INSERT...SELECTdeclaração. Por motivos de arquitetura, desejo gerar os identificadores do lado do servidor nesse caso.

Como posso gerar uma aleatoriamente segura UNIQUEIDENTIFIER? Observe que NEWIDisso não seria aleatório o suficiente, pois não promete nenhuma propriedade de segurança. Estou procurando o equivalente do SQL Server System.Security.Cryptography.RandomNumberGenerator porque preciso de IDs indiscutíveis. Qualquer coisa baseada em CHECKSUM, RANDou GETUTCDATEtambém não se qualificaria.

usr
fonte
2
@AaronBertrand, no mínimo, um se os dígitos forem sempre 4. Mas o fato de eu não ter fortes evidências de que possam ser adivinhadas não significa que não. Não posso basear essa decisão de segurança nessa observação.
usr
1
Talvez NEWID é tão aleatório como os "Debian fraco chaves SSH": en.wikinews.org/wiki/... Eles certamente parecia aleatória para o desenvolvedor que eles testaram ...
usr
2
Esse 4 diz qual algoritmo é usado na geração do GUID. en.wikipedia.org/wiki/Globally_unique_identifier#Algorithm
Mr.Mindor 04/04
1
Você entende que o único fator determinante no nível de sua segurança é a entropia de bits? A idéia de que NEWID não seja aleatória o suficiente para suas necessidades implicaria que você tivesse alguma idéia da quantidade de entropia de bits necessária para ser "segura" para o seu caso de uso. Qual é esse número?
Cade Roux
2
@usr - "dado pleno conhecimento do estado interno", pode-se quebrar qualquer abordagem.

Respostas:

26
SELECT CAST(CRYPT_GEN_RANDOM(16) AS UNIQUEIDENTIFIER)

Deveria fazer o truque que eu teria pensado.

CRYPT_GEN_RANDOM

Retorna um número aleatório criptográfico gerado pela API de criptografia (CAPI).

Martin Smith
fonte
4

Apenas meus dois centavos, mas isso pode não ser uma boa ideia. Parafraseando a excelente série de Eric Lippert nos GUIDs ( parte 1 , parte 2 , parte 3 ), o acrônimo é GUID, não GSUID - Identificador Globalmente Único, não Identificador Único Globalmente Seguro.

O problema reside no fato de que, quando os GUIDs são gerados em um escopo não hostil, como todos que usam NEWID (), todos os valores são garantidos como únicos (bem, mais ou menos, consulte o artigo de Eric, parte 3). Porém, se uma entidade hostil entrar nesse escopo, poderá prever o próximo GUID gerado e causar colisões por conta própria.

Ao criar seu próprio método de gerar um valor que você armazena dentro de uma estrutura que se parece com um GUID, você se tornou essencialmente uma entidade hostil. Você alterou o contrato de um GUID de exclusivo para aleatório . Enquanto alguém melhor em matemática do que eu provavelmente poderia provar que você ainda é único, isso está apenas dentro dos limites do seu método de geração. Se você combinar esses pseudo-GUIDs com os NEWID () GUIDs, todas as apostas serão desativadas.

Eu digo que isso pode não ser uma boa idéia apenas porque não conheço todo o escopo de como você está usando os valores. Se você é a única entidade que gera os valores (sem combinação e correspondência) e / ou não persiste nos valores e / ou não se importa com colisões, isso pode não ser um problema. Se algum desses itens não for verdadeiro, convém reavaliar.

Dave Simione
fonte
Pontos interessantes. Minha escolha de tipo de dados UNIQUEIDENTIFIERé principalmente uma coincidência. É conveniente lidar com uma quantidade de 16 bytes usando esse tipo. Eu penso nisso como uma senha. Tem que ser único, no entanto. Estou confiante de que nunca virei uma colisão (e mesmo se houver o aplicativo falhará - também é seguro).
usr
Não concordo, depende de 'como' você o criptografará se ele se tornar aleatório e não único. Pode ser facilmente o mesmo.
Dawesi
4

De acordo com https://blogs.msdn.microsoft.com/sqlprogrammability/2006/03/23/newsequentialid-histrorybenefits-and-implementation/ , a função NEWID () apenas envolve a função do Windows CoCreateGuid, que retorna um GUID no estilo v4 . E de acordo com https://msdn.microsoft.com/en-us/library/bb417a2c-7a58-404f-84dd-6b494ecf0d13#id11 , desde o Windows 2000 em 1999,

"os bits aleatórios para todos os GUIDs da versão 4 criados no Windows são obtidos através da API criptográfica Windows CryptGenRandom ou equivalente, a mesma fonte usada para a geração de chaves criptográficas"

Então, eu diria que você poderia considerar NEWID () criptograficamente seguro - pelo menos na extensão dos 122 bits de entropia que ele fornece.

Jordan Rieger
fonte
Isso é interessante. Eu, pessoalmente, não confiaria nisso por motivos de segurança. Nem o Windows nem o SQL Server garantem isso.
usr
@usr Não tenho certeza de como seria uma garantia. Ele não usa a palavra "garantia", mas parece ser a documentação padrão do MSDN Windows SDK. Seria extremamente improvável que a Microsoft rebaixasse a aleatoriedade criptográfica dos GUIDs em alguma versão futura do Windows. Não haveria nada a ganhar.
Jordan Rieger
Essa página do MSDN apenas documenta opções históricas, mas não diz que isso será mantido no futuro. O mesmo para o SQL Server. Não consigo imaginar circunstâncias sob as quais isso iria desmoronar. Mas tem havido muitos desastres catastróficos do RNG. Pressupostos como esse geralmente se revelam falsos. É um argumento heurístico.
usr
@usr Mas como poderia qualquer documentação do MSDN garantir o comportamento futuro do Windows? O máximo que podemos esperar nesses casos é a documentação do comportamento atual. Se o comportamento mudar, eles atualizam a documentação. É por isso que essas perguntas e respostas sobre estouro de pilha têm tags de versão e são atualizadas periodicamente.
Jordan Rieger
Eles garantem coisas que não vão mudar. Eles podem mudar o produto, mas não o fazem se disserem "aqui está uma função crítica de segurança com essas propriedades". Interpreto essa documentação em questão mais como uma visão histórica do que uma afirmação sobre o futuro.
usr