짧은 답변
왜 난 그냥 말할 수 없습니다 :
SecureString password = new SecureString("password");
지금 당신은 password
메모리에 있기 때문에 ; 그것을 닦을 방법이 없습니다-정확히 요점입니다. SecureString .
긴 답변
SecureString 이 존재 하는 이유 는 중요한 데이터를 다룰 때 ZeroMemory 를 사용 하여 중요한 데이터를 지울 수 없기 때문 입니다. 존재하는 문제를 해결하기 위해 존재합니다 .CLR로 .
일반 네이티브 응용 프로그램에서는 다음을 호출합니다 SecureZeroMemory
.
메모리 블록을 0으로 채 웁니다.
참고 : SecureZeroMemory이다는 동일 ZeroMemory
, 컴파일러를 제외하고 멀리 최적화되지 않습니다.
문제는 전화를 걸 거나 .NET 내부에서 할 수 없다는 것 입니다. 그리고 .NET에서 문자열은 변경할 수 없습니다. 다른 언어에서와 같이 문자열의 내용을 덮어 쓸 수도 없습니다 .ZeroMemory
SecureZeroMemory
//Wipe out the password
for (int i=0; i<password.Length; i++)
password[i] = \0;
그래서 당신은 무엇을 할 수 있습니까? .NET에서 암호 나 신용 카드 번호를 메모리에서 지울 수있는 기능을 어떻게 제공합니까?
그것을 할 수있는 유일한 방법은 일부 문자열을 배치하는 것입니다 네이티브 는 메모리 블록, 수 후 전화 ZeroMemory
. 다음과 같은 기본 메모리 객체 :
- BSTR
- HGLOBAL
- CoTaskMem 비 관리 메모리
SecureString은 잃어버린 능력을 돌려줍니다.
.NET에서 문자열을 완료하면 문자열을 지울 수 없습니다.
- 그들은 불변이다. 당신은 그들의 내용을 덮어 쓸 수 없습니다
- 당신
Dispose
은 그들 중 누구도
- 그들의 청소는 가비지 수집기의 자비에 있습니다
SecureString은 문자열 안전을 전달하는 방법으로 존재하며 필요할 때 정리를 보장 할 수 있습니다.
당신은 질문을했다 :
왜 난 그냥 말할 수 없습니다 :
SecureString password = new SecureString("password");
지금 당신은 password
메모리에 있기 때문에 ; 닦을 방법이 없습니다. CLR이 해당 메모리를 재사용하기로 결정할 때까지 중단됩니다. 당신은 우리가 시작한 곳으로 우리를 바로 돌려 놓았습니다. 우리가 제거 할 수없는 암호가있는 실행중인 응용 프로그램과 메모리 덤프 (또는 프로세스 모니터)가 암호를 볼 수있는 곳.
SecureString은 Data Protection API를 사용하여 메모리에 암호화 된 문자열을 저장합니다. 그런 식으로 스왑 파일, 크래시 덤프 또는 로컬 변수 창에 문자열이 존재하지 않아야합니다.
비밀번호는 어떻게 읽습니까?
그렇다면 질문은 : 문자열과 어떻게 상호 작용합니까? 당신은 절대적으로 다음 과 같은 방법을 원하지 않습니다 :
String connectionString = secureConnectionString.ToString()
이제 시작한 곳으로 바로 돌아갈 수 있기 때문에 제거 할 수없는 비밀번호입니다. 당신은 할 강제 제대로 민감한 문자열을 처리하기 위해 개발자 - 너무 것을 할 수 메모리에서 닦아.
따라서 .NET은 SecureString을 관리되지 않는 메모리에 마샬링하는 세 가지 편리한 도우미 함수를 제공합니다.
문자열을 관리되지 않는 메모리 얼룩으로 변환하고 처리 한 다음 다시 지 웁니다.
일부 API는 SecureStrings를 허용 합니다. 예를 들어 ADO.net 4.5에서 SqlConnection.Credential 은 SqlCredential 세트를 가져옵니다 .
SqlCredential cred = new SqlCredential(userid, password); //password is SecureString
SqlConnection conn = new SqlConnection(connectionString);
conn.Credential = cred;
conn.Open();
연결 문자열 내에서 비밀번호를 변경할 수도 있습니다.
SqlConnection.ChangePassword(connectionString, cred, newPassword);
그리고 .NET 내부에는 호환성을 위해 일반 문자열을 계속 수용 한 다음 SecureString으로 빠르게 전환합니다.
SecureString에 텍스트를 넣는 방법?
여전히 문제가 남아 있습니다.
처음에 SecureString에 비밀번호를 얻으려면 어떻게해야합니까?
이것은 도전이지만, 요점은 보안에 대해 생각하게하는 것입니다.
때로는 기능이 이미 제공되어 있습니다. 예를 들어, WPF PasswordBox 컨트롤은 입력 한 암호를 SecureString으로 직접 반환 할 수 있습니다.
PasswordBox가 현재 보유하고있는 비밀번호 를 SecureString 으로 가져옵니다 .
이것은 원시 문자열을 전달하는 데 사용되는 모든 곳에서 SecureString이 String과 호환되지 않는다고 불평하는 유형 시스템을 가지고 있기 때문에 유용합니다. SecureString을 다시 일반 문자열로 변환하기 전에 가능한 한 오래 가고 싶습니다.
SecureString 변환은 충분히 쉽습니다.
- SecureStringToBSTR
- PtrToStringBSTR
에서와 같이 :
private static string CreateString(SecureString secureString)
{
IntPtr intPtr = IntPtr.Zero;
if (secureString == null || secureString.Length == 0)
{
return string.Empty;
}
string result;
try
{
intPtr = Marshal.SecureStringToBSTR(secureString);
result = Marshal.PtrToStringBSTR(intPtr);
}
finally
{
if (intPtr != IntPtr.Zero)
{
Marshal.ZeroFreeBSTR(intPtr);
}
}
return result;
}
그들은 단지 당신이 그것을하고 싶지 않습니다.
그러나 SecureString에 문자열을 어떻게 가져 옵니까? 글쎄, 당신이해야 할 일은 처음에 문자열 에 암호를 갖는 것을 멈추는 것입니다. 당신은 다른 것을 가지고 있어야했습니다 . 심지어Char[]
배열 도움이 될 것입니다.
각 문자를 추가 할 수 있습니다 때이다 그리고 이 완료되면 일반 텍스트를 닦아 :
for (int i=0; i < PasswordArray.Length; i++)
{
password.AppendChar(PasswordArray[i]);
PasswordArray[i] = (Char)0;
}
초기화 할 수 있는 일부 메모리에 비밀번호가 저장되어 있어야합니다 . 거기에서 SecureString에로드하십시오.
tl; dr : SecureString 은 ZeroMemory 와 동등한 기능을 제공합니다. .
어떤 사람들은에 지점이 표시되지 않는 장치가 잠겨있을 때 메모리에서 사용자의 암호를 닦아 , 또는 닦아 they'authenticated 후 메모리에서 닦아 키 입력을 . 그 사람들은 SecureString을 사용하지 않습니다.
SecureString
새로운 개발을 권장하지 않습니다 : github.com/dotnet/platform-compat/blob/master/docs/DE0001.md