[c#] 결정적 가이드를 만드는 방법

우리의 응용 프로그램에서 우리는 Guid 값을 가진 속성을 가진 Xml 파일을 만들고 있습니다. 이 값은 파일 업그레이드간에 일관성이 있어야했습니다. 따라서 파일의 다른 모든 항목이 변경 되더라도 속성의 guid 값은 동일하게 유지되어야합니다.

한 가지 분명한 해결책은 파일 이름과 사용할 Guid로 정적 사전을 만드는 것이 었습니다. 그런 다음 파일을 생성 할 때마다 파일 이름에 대한 사전을 찾고 해당 guid를 사용합니다. 그러나 이것은 100 개의 파일로 확장 할 수 있고 GUID의 큰 목록을 유지하고 싶지 않기 때문에 실현 가능하지 않습니다.

그래서 또 다른 접근 방식은 파일 경로를 기반으로 Guid를 동일하게 만드는 것입니다. 파일 경로와 응용 프로그램 디렉토리 구조는 고유하므로 Guid는 해당 경로에 대해 고유해야합니다. 따라서 업그레이드를 실행할 때마다 파일은 경로에 따라 동일한 GUID를 가져옵니다. 그런 ‘ 결정적 가이드 ‘ 를 생성하는 멋진 방법을 찾았습니다 (Elton Stoneman에게 감사합니다). 기본적으로 다음과 같이합니다.

private Guid GetDeterministicGuid(string input) 

{ 

//use MD5 hash to get a 16-byte hash of the string: 

MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider(); 

byte[] inputBytes = Encoding.Default.GetBytes(input); 

byte[] hashBytes = provider.ComputeHash(inputBytes); 

//generate a guid from the hash: 

Guid hashGuid = new Guid(hashBytes); 

return hashGuid; 

} 

따라서 문자열이 주어지면 Guid는 항상 동일합니다.

이를 수행하는 다른 접근 방식이나 권장되는 방법이 있습니까? 그 방법의 장단점은 무엇입니까?



답변

@bacar에서 언급했듯이 RFC 4122 §4.3 은 이름 기반 UUID를 만드는 방법을 정의합니다. (MD5 해시를 사용하는 것보다)이 작업의 장점은 이름이 지정되지 않은 UUID와 충돌하지 않으며 다른 이름 기반 UUID와 충돌 할 가능성이 매우 적다는 것입니다.

.NET Framework에서 이러한 생성을위한 기본 지원은 없지만 알고리즘을 구현하는 코드를 GitHub에 게시했습니다 . 다음과 같이 사용할 수 있습니다.

Guid guid = GuidUtility.Create(GuidUtility.UrlNamespace, filePath);

다른 GUID와의 충돌 위험을 더욱 줄이기 위해 RFC에 정의 된 URL 네임 스페이스 ID를 사용하는 대신 네임 스페이스 ID로 사용할 개인 GUID를 만들 수 있습니다.


답변

이렇게하면 외부 어셈블리를 가져올 필요없이 모든 문자열을 Guid로 변환합니다.

public static Guid ToGuid(string src)
{
    byte[] stringbytes = Encoding.UTF8.GetBytes(src);
    byte[] hashedBytes = new System.Security.Cryptography
        .SHA1CryptoServiceProvider()
        .ComputeHash(stringbytes);
    Array.Resize(ref hashedBytes, 16);
    return new Guid(hashedBytes);
}

고유 한 Guid를 생성하는 훨씬 더 좋은 방법이 있지만 이것은 문자열 데이터 키를 Guid 데이터 키로 지속적으로 업그레이드하는 방법입니다.


답변

Rob이 언급했듯이 메서드는 UUID를 생성하지 않고 UUID처럼 보이는 해시를 생성합니다.

UUID 의 RFC 4122 는 특히 결정적 (이름 기반) UUID를 허용합니다. 버전 3 및 5는 md5 및 SHA1 (각각)을 사용합니다. 대부분의 사람들은 아마도 무작위 버전 4에 익숙 할 것입니다. Wikipedia 는 버전에 대한 좋은 개요를 제공합니다. (여기서 ‘버전’이라는 단어의 사용은 UUID의 ‘유형’을 설명하는 것처럼 보입니다. 버전 5는 버전 4를 대체하지 않습니다.)

python uuid 모듈 , boost.uuid (C ++) 및 OSSP UUID를 포함하여 버전 3/5 UUID를 생성하기위한 몇 가지 라이브러리가있는 것 같습니다 . (나는 .net을 찾지 못했습니다)


답변

클래스의 인스턴스 Guid와 전역 적으로 고유 한 식별자를 구분해야합니다. “결정적 GUID”는 실제로 해시입니다 (를 호출하여 입증 됨 provider.ComputeHash). 해시는를 통해 생성 된 Guid보다 충돌 (동일한 해시를 생성하기 위해 발생하는 두 개의 다른 문자열) 가능성이 훨씬 높습니다 Guid.NewGuid.

따라서 접근 방식의 문제는 두 개의 다른 경로가 동일한 GUID를 생성 할 가능성에 대해 괜찮아 야한다는 것입니다. 주어진 경로 문자열에 대해 고유 한 식별자가 필요한 경우 가장 쉬운 방법 은 문자열을 사용하는 것 입니다. 사용자에게 가려진 문자열이 필요한 경우 암호화하십시오. ROT13 또는 더 강력한 것을 사용할 수 있습니다.

순수한 GUID가 아닌 것을 GUID 데이터 유형에 통합하려고하면 향후 유지 관리 문제가 발생할 수 있습니다.


답변

MD5는 약합니다. SHA-1로도 똑같은 일을하고 더 나은 결과를 얻을 수 있다고 믿습니다.

BTW는 개인적인 의견 일뿐 md5 해시를 GUID로 꾸미는 것은 좋은 GUID가되지 않습니다. 본질적으로 GUID는 비 결정적입니다. 이것은 속임수처럼 느껴집니다. 스페이드를 스페이드라고 부르고 입력의 문자열로 렌더링 된 해시라고 말하면 안됩니다. 새로운 guid 라인 대신 다음 라인을 사용하여이를 수행 할 수 있습니다.

string stringHash = BitConverter.ToString(hashBytes)


답변