서비스 계정 자격 증명을 사용하여 배치 파일 프로세스를 실행하는 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을 사용하여 한 시간 내에 문제를 해결할 수 있다고 말했습니다. 응용 프로그램 내에 이러한 자격 증명을 저장하는 가장 좋은 방법은 무엇입니까?
하드 코드 된 키를 완전히 저장할 수 없습니다. 적어도 런타임에는 키를 가져와야하고 디버거는 간단히 키를 가져올 수 있습니다. 키 저장에 대한 아이디어는 잊어 버리십시오. 전용 서버 등으로 작업하면 보안 성이 향상 될 수 있습니다. –
공격자가 DB를 얻으면 암호를 암호화하지 마십시오. 암호 키도 받게됩니다. 암호를 인터넷에 연결된 서버에서 사용할 수 없도록하려면 다른 sertver 또는 HSM에서 암호화를 수행해야합니다. – zaph
나는 응용 프로그램 내에 저장하면 절대로 100 % 안전하지 않을 것이라고 완전히 동의합니다. 전용 서버는 보안을 향상시킬 수 있다고 언급합니다. 이 서버에 키를 저장하고 런타임 중에 SecureString으로 가져 와서 startinfo 속성에 전달한다는 의미일까요? – CodeIsLoveAndLife