2016-11-14 4 views
2

서비스 계정 자격 증명을 사용하여 배치 파일 프로세스를 실행하는 ClickOnce 응용 프로그램을 작성하고 있습니다. 프로세스가 실행되기 전에 프로그램이 process.startinfo 속성에 사용자 이름/암호를 추가 할 수 있도록 서비스 계정 자격 증명을 저장해야합니다. 사용자는이 암호를 모르므로 암호를 입력하라는 메시지가 표시되지 않습니다. 나는 이것이 내가 해쉬를 저장할 수없고 패스워드를 검증 할 수 없다는 것을 의미한다고 믿는다. 해시 값은 되돌릴 수 있어야한다. 그래서 startinfo 속성에 올바른 암호를 추가 할 수있다. 이 사이트를 검색하여 작동하는 Frankenstein 형 솔루션을 제안했지만 매우 안전하지는 않습니다. 현재이 방법을 사용하여 암호를 암호화하고 암호화 된 값을 저장 한 다음 암호 해독 방법을 사용하여 런타임 중에 암호를 얻습니다. 암호화 메서드는 런타임 중에 실행되지 않으며 디버깅하는 동안 Visual Studio에서 실행되고 값을 복사 한 다음, 그러나, 나는 그것이 안전하지 않은 것을 알고,Clickonce 응용 프로그램에 서비스 계정 자격 증명을 안전하게 저장

private string GetServiceAcctPW() 
    { 

     // Declare the RijndaelManaged object 
     // used to decrypt the data. 
     RijndaelManaged aesAlg = null; 

     // Declare the string used to hold 
     // the decrypted text. 
     string plaintext = null; 

     try 
     { 
      // generate the key from the shared secret and the salt 
      Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedsecret, _salt); 

      // Create the streams used for decryption.     
      byte[] bytes = Convert.FromBase64String("EncryptedValueHere"); 
      using (MemoryStream msDecrypt = new MemoryStream(bytes)) 
      { 
       // Create a RijndaelManaged object 
       // with the specified key and IV. 
       aesAlg = new RijndaelManaged(); 
       aesAlg.Key = key.GetBytes(aesAlg.KeySize/8); 
       // Get the initialization vector from the encrypted stream 
       aesAlg.IV = ReadByteArray(msDecrypt); 
       // Create a decrytor to perform the stream transform. 
       ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); 
       using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 
       { 
        using (StreamReader srDecrypt = new StreamReader(csDecrypt)) 

         // Read the decrypted bytes from the decrypting stream 
         // and place them in a string. 
         plaintext = srDecrypt.ReadToEnd(); 
       } 
      } 
     } 
     catch(Exception e) 
     { 
      Console.WriteLine("Error decrypting password"); 
      Console.WriteLine(e.StackTrace); 
      logger.WriteToLog(Logger.LogCodes.ERROR, "Error decrypting service account password"); 
      MessageBox.Show("An error occurred while trying to start the installation process\nPlease contact the Service Desk for further assistance"); 
     } 
     finally 
     { 
      // Clear the RijndaelManaged object. 
      if (aesAlg != null) 
       aesAlg.Clear(); 
     } 

     return plaintext; 
    } 

이 코드는 잘 작동합니다 :

// used to generate decrypted acct creds 
    private void EncryptText(string plaintext) 
    { 
     string outsrt = null; 
     RijndaelManaged aesAlg = null; 

     try 
     { 
      // generate key from secret and salt 
      Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedsecret, _salt); 

      aesAlg = new RijndaelManaged(); 
      aesAlg.Key = key.GetBytes(aesAlg.KeySize/8); 

      ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); 

      using (MemoryStream mEncrypt = new MemoryStream()) 
      { 
       // prepend the IV 
       mEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int)); 
       mEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length); 
       using (CryptoStream csEncrypt = new CryptoStream(mEncrypt, encryptor, CryptoStreamMode.Write)) 
       { 
        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
        { 
         // write all data to the stream 
         swEncrypt.Write(plaintext); 
        } 
       } 

       outsrt = Convert.ToBase64String(mEncrypt.ToArray()); 
      } 
     } 
     finally 
     { 
      if (aesAlg != null) 
       aesAlg.Clear(); 
     } 

     Console.WriteLine(outsrt); 
    } 

가 여기에 해독 방법이다 : 다음이 아래의 해독 방법에서 그 값)을 사용했다. 코드 검토 담당자는 난독 화 레이어 만 추가하기 때문에 dotPeek을 사용하여 한 시간 내에 문제를 해결할 수 있다고 말했습니다. 응용 프로그램 내에 이러한 자격 증명을 저장하는 가장 좋은 방법은 무엇입니까?

+1

하드 코드 된 키를 완전히 저장할 수 없습니다. 적어도 런타임에는 키를 가져와야하고 디버거는 간단히 키를 가져올 수 있습니다. 키 저장에 대한 아이디어는 잊어 버리십시오. 전용 서버 등으로 작업하면 보안 성이 향상 될 수 있습니다. –

+0

공격자가 DB를 얻으면 암호를 암호화하지 마십시오. 암호 키도 받게됩니다. 암호를 인터넷에 연결된 서버에서 사용할 수 없도록하려면 다른 sertver 또는 HSM에서 암호화를 수행해야합니다. – zaph

+0

나는 응용 프로그램 내에 저장하면 절대로 100 % 안전하지 않을 것이라고 완전히 동의합니다. 전용 서버는 보안을 향상시킬 수 있다고 언급합니다. 이 서버에 키를 저장하고 런타임 중에 SecureString으로 가져 와서 startinfo 속성에 전달한다는 의미일까요? – CodeIsLoveAndLife

답변

1

암호화 키는 전용 서버에 있습니다.

암호는 암호화 할 ID와 DB 저장을 위해 반환 된 암호화 된 암호와 함께 서버로 전송됩니다.

암호가 필요하면 id로 전용 서버에 요청하고 암호가 해독 된 암호가 반환됩니다.

암호는 디스크에 저장되지 않으며 전용 서버에서 키를 사용할 수 없습니다.

전용 서버는 가난한 사람의 HSM과 비슷합니다.

이것은 해시가 아닌 암호화 된 것입니다. 암호화 키는 전용 서버에서 ID와 함께 저장되는 임의의 IV와 함께 비밀입니다. 키는 사용할 수 없으며 암호와 관련이 없으므로 기본적으로 무차별 공격에 취약한 암호화 키에 대한 무차별 공격보다 더 좋은 공격은 없습니다.

서버는 매우 안전해야하며, 두 개의 요인 로그인 만 있으면되고 인터넷에서는 사용할 수 없습니다.

+0

아, 알겠습니다. 따라서 이러한 값에 대한 암호화, 암호 해독 및 저장을 처리하는 전용 서버가 있어야 내 응용 프로그램에서 이러한 값 자체를 저장하지 않습니다. 응용 프로그램은 단순히 ID로 서버에 손을 뻗어서 서버는 해독 된 암호로 응답해야합니다. 이런 종류의 스 니펫을 가지고 있습니까? 아니면 좋은 방향으로 나를 가르쳐 주시겠습니까? – CodeIsLoveAndLife

+0

네, 맞습니다. 죄송합니다. 코드를 도울 수 없으며 그러한 코드가 없습니다. – zaph

+0

걱정할 필요가 없으므로 안내에 대단히 감사하겠습니다. 이것은 이미 큰 도움이되며 적절한 해결책을 찾도록 안내 할 것입니다. 나는 다른 팀과 함께 서버를 작동시켜야 할 것이지만, 나는이 아이디어를 좋아한다. – CodeIsLoveAndLife