2017-12-01 7 views
0

사용자로부터 수집해야하는 중요한 정보가 있습니다. 이 정보를 요청하려면 WPF PasswordBox을 사용하고 있습니다. 초창기의 경우 PasswordBox 컨트롤은 개체가 아닌 SecureString 개체 인 SecurePassword 속성을 제공합니다. 신청서 내에서 PasswordBox의 데이터는 SecureString으로 암호화 방법으로 전달됩니다.SecureString에서 바이너리 데이터를 올바르게 내보내 어떻게 나중에 문자열로 변환 할 수 있습니까?

내가 할 수 있어야 할 것은 기본적으로 .Net string으로 데이터를 변환하지 않고 닷넷 string 값을 나타내는 바이트 배열로 마샬링하는 것입니다. !보다 구체적

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890` ~ @ # $으로의 % ...과 같은 값을 갖는 주어진 SecureString & * ^() _- + = {[}] | :; " '<>. ?/≈ 篭 母

... 나는 StreamWriter?

으로 직렬화 및 스트림에 기록 된 것 닷넷 문자열이 해당하는 바이트 배열로 변환 할 수있는 방법 Marshal.SecureStringToCoTaskMemUnicode(...)을 사용하여 보다 전통적인 서구 텍스트로이를 수행하십시오. 그러나 위의 텍스트 문자열을 추가로, 일반이 아닌 문자 및 일본어 텍스트 문자열을 사용하여 만든 경우 (마지막 몇 개의 굵은 문자 참조) 유니 코드 바이트 배열을 IntPtr 위치에 할당하는 방법이 제대로 작동하지 않는 것 같습니다. 더 이상.

SecureString의 데이터를 안전하게 반환하여 반환 된 바이트 데이터가 표준 .Net 문자열의 바이트 데이터와 동일하게 구조화되고 이진 출력으로 직렬화되도록하려면 어떻게해야합니까?

참고

순간에 모든 보안 문제를 무시하십시오. 내 응용 프로그램에 대한 다양한 보안 업그레이드 작업을하고 있습니다. 지금은 민감한 데이터를 암호화 장치로 가져 오는 데 SecureString을 사용해야합니다. decryptor (지금은)이 데이터를 string 값으로 해독해야합니다. 따라서 SecureString의 데이터를 string 개체의 이진 형식과 비슷한 방식으로 직렬화해야합니다.

이 접근 방식은 약간 불행한 점에 동의하지만 기존 응용 프로그램을 점진적으로 개선해야하며 첫 번째 단계는 SecureString 개체의 데이터를 암호화 장치로 잠그는 것입니다. 당신은 스트리밍 보안 문자열을 작성해야하는 경우

+0

https://codereview.stackexchange.com/a/107864/5297? – stuartd

+0

이것은 약간의 용의자로 들리는데, 특정 사물을 잠그는 경우 왜 암호 정보가 필요합니까? 네트워크 공유, 폴더, 데이터베이스 등과 같은 무단 액세스를 방지하기 위해 취할 수있는 다른 방법/접근법이 있습니다. 당신은 정말로 당신이 잠그고 자하는 것이 무엇인지를 설명합니다. – MethodMan

+0

@MethodMan 내 노트를 참조하십시오. 우리의 응용 프로그램은 중요한 정보를 수집하고, 보안 키를 사용하여 암호화하고, 다른 로켈에서 암호 해독 된 암호화 된 데이터를 배포해야합니다. 결국 두 번째 지점의 코드를 업데이트하여 데이터의 암호를 해독하고 세부 정보를 SecureStrings에 보관합니다. 그러나, 내가 말했듯이, 나는 다단계 프로세스에서 이것을 할 필요가있다. 현재 암호화를 담당하는 응용 프로그램은 해독 된 세부 사항을 .Net 문자열로 쉽게 다시 변환 할 수있는 방식으로 데이터를 방출해야합니다. – RLH

답변

1

,이 같은 방법을 만드는 게 좋을 것 : 당신이 정말로 바이트 배열을해야하는 경우

public static class Extensions { 
    public static void WriteSecure(this StreamWriter writer, SecureString sec) { 
     int length = sec.Length; 
     if (length == 0) 
      return; 
     IntPtr ptr = Marshal.SecureStringToBSTR(sec); 
     try { 
      // each char in that string is 2 bytes, not one (it's UTF-16 string) 
      for (int i = 0; i < length * 2; i += 2) { 
       // so use ReadInt16 and convert resulting "short" to char 
       var ch = Convert.ToChar(Marshal.ReadInt16(ptr + i)); 
       // write 
       writer.Write(ch); 
      } 
     } 
     finally { 
      // don't forget to zero memory 
      Marshal.ZeroFreeBSTR(ptr); 
     } 
    } 
} 

이 - 당신도이 방법을 다시 사용할 수 있습니다 :

byte[] result; 
using (var ms = new MemoryStream()) { 
    using (var writer = new StreamWriter(ms)) { 
     writer.WriteSecure(secureString); 
    } 
    result = ms.ToArray(); 
} 

첫 번째 댓글의 방법이 조금 더 재미있을 수도 있지만 (중요한지 확실하지 않음)