2010-05-13 2 views
4

오늘 웹 응용 프로그램을 .net 4.0으로 옮겼으며 Forms Auth가 작동을 멈췄습니다. 내 SqlMembershipProvider (내장 된 SqlMembershipProvider의 단순화 된 버전)를 몇 시간 파고 들자 마자 HMACSHA256 해시가 일관성이 없다는 것을 알았습니다. 다음은 암호화 방법입니다..NET 4.0에서 잘못된 암호 오류가 발생했습니다.

internal string EncodePassword(string pass, int passwordFormat, string salt) 
{ 
    if (passwordFormat == 0) // MembershipPasswordFormat.Clear 
     return pass; 

    byte[] bIn = Encoding.Unicode.GetBytes(pass); 
    byte[] bSalt = Convert.FromBase64String(salt); 
    byte[] bAll = new byte[bSalt.Length + bIn.Length]; 
    byte[] bRet = null; 

    Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length); 
    Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length); 
    if (passwordFormat == 1) 
    { // MembershipPasswordFormat.Hashed 
     HashAlgorithm s = HashAlgorithm.Create(Membership.HashAlgorithmType); 
     bRet = s.ComputeHash(bAll); 
    } else 
    { 
     bRet = EncryptPassword(bAll); 
    } 

    return Convert.ToBase64String(bRet); 
} 

동일한 암호와 소금을 두 번 입력하면 결과가 달라집니다 !!! .NET 3.5에서 완벽하게 작동했습니다.

심각한 변경 사항을 알고 있거나 알려진 버그입니까?

업데이트 : 해시 알고리즘으로 SHA512를 지정하면, 모든 것이 잘 작동, 그래서 감사

.NET 4.0은 HMACSHA256 해시 알고리즘의 구현에 버그 믿는다! 안드레이

나는 이것 좀 봐 .NET 4.0의 몇 가지 보안 관련 변경 사항이 있었다 생각

답변

2

...

http://www.asp.net/(S(ywiyuluxr3qb2dfva1z5lgeg))/learn/whitepapers/aspnet4/breaking-changes

튀어 첫 번째 분명한 것은이 ...

입니다

기본 해싱 알고리즘 HMACSHA256

ASP.NET은 암호화 및모두 사용 지금양식 인증 쿠키 및보기 상태와 같은 데이터 의 보안을 돕는 해시 알고리즘. 기본적으로 ASP.NET 4 은 쿠키의 해시 작업에 HMACSHA256 알고리즘을 사용하고 상태를 봅니다. 이전 버전의 ASP.NET 은 이전 HMACSHA1 알고리즘을 사용했습니다.

귀하의 응용 프로그램은 ASP.NET 2.0을 혼합 실행할 경우 영향을받을 수 있습니다/ASP.NET과 같은 데이터가 across.NET 프레임 워크 버전을 일해야 인증 쿠키를 형성하는 4 개 환경.

 <machineKey validation="SHA1" /> 

가 명시 적으로 설정하여 해싱 알고리즘을하거나 보자 구성 이전 HMACSHA1 알고리즘을 사용하는 ASP.NET 4 웹 응용 프로그램 에, 는 Web.config 파일에 다음 설정을 추가 asp.net 결정 ... 다른 기본값을 사용하고 있다면 정의 된 알고리즘이 더 이상 지원되지 않으므로 임의의 이전 해싱 알고리즘을 무작위로 잡을 수 있습니다.

M $는 사용중인 제품을 폐기했을 수 있습니다. 따라서 원인이 될 수 있습니다. 험담하는 사람 ... 저는 방금 CMS를 테스트해야한다는 것을 깨달았습니다. .

머리를 주셔서 감사합니다, 잘만되면 나의 생각은 우리를 양쪽 다 도울 것이다!

2

이 문제도 발생했습니다.

최종 목표는 connectionString을 동적으로 설정할 수있게하는 것이 었습니다 (web.config에 하드 코딩 된 대신). 나는 MS가 ASP에 내놓은 소스 코드를 다운로드하여이 작업을 수행했다.NET 공급자 및 연결 문자열을 가져 오기위한 일부 내부 기능 변경.

그러나 이것은 .NET 2.0 용이었고 Andrey 코드가 위와 같이 게시 한 것처럼 보입니다. 일단 모든 것을 제자리에 잡히면 내 웹 사이트에 로그인 할 수 없다는 것을 알았습니다. 그래서 검색 후 나는이 게시물을 발견했다. 감사!

.NET Framework 4.0 코드를 다운로드하고 여기 (아무도 알고 싶다면) EncodePassword 메서드의 새 버전을 다운로드했습니다. 이것을 새로운 버전의 SqlMembershipProvider로 복사하여 새로운 암호화 방법을 사용하고 ASP.NET 4.0 웹 사이트에 다시 로그인 할 수있게 할 계획입니다!

private string EncodePassword(string pass, int passwordFormat, string salt) 
    { 
     if (passwordFormat == 0) // MembershipPasswordFormat.Clear 
      return pass; 

     byte[] bIn = Encoding.Unicode.GetBytes(pass); 
     byte[] bSalt = Convert.FromBase64String(salt); 
     byte[] bRet = null; 

     if (passwordFormat == 1) 
     { // MembershipPasswordFormat.Hashed 
      HashAlgorithm hm = GetHashAlgorithm(); 
      if (hm is KeyedHashAlgorithm) { 
       KeyedHashAlgorithm kha = (KeyedHashAlgorithm) hm; 
       if (kha.Key.Length == bSalt.Length) { 
        kha.Key = bSalt; 
       } else if (kha.Key.Length < bSalt.Length) { 
        byte[] bKey = new byte[kha.Key.Length]; 
        Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length); 
        kha.Key = bKey; 
       } else { 
        byte[] bKey = new byte[kha.Key.Length]; 
        for (int iter = 0; iter < bKey.Length;) { 
         int len = Math.Min(bSalt.Length, bKey.Length - iter); 
         Buffer.BlockCopy(bSalt, 0, bKey, iter, len); 
         iter += len; 
        } 
        kha.Key = bKey; 
       } 
       bRet = kha.ComputeHash(bIn); 
      } 
      else { 
       byte[] bAll = new byte[bSalt.Length + bIn.Length]; 
       Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length); 
       Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length); 
       bRet = hm.ComputeHash(bAll); 
      } 
     } else { 
      byte[] bAll = new byte[bSalt.Length + bIn.Length]; 
      Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length); 
      Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length); 
      bRet = EncryptPassword(bAll, _LegacyPasswordCompatibilityMode); 
     } 

     return Convert.ToBase64String(bRet); 
    } 

편집 :이 방법 중 하나를 SqlMembershipProvider의 이전 버전으로 복사하려고 시도하는 것은 좋지 않습니다. 너무 많이 변경되었습니다. :(