วิธีแปลงString
เป็นSecureString
?
วิธีแปลงString
เป็นSecureString
?
คำตอบ:
คุณไม่ทำ เหตุผลทั้งหมดในการใช้อ็อบเจ็กต์ SecureString คือการหลีกเลี่ยงการสร้างอ็อบเจ็กต์สตริง (ซึ่งโหลดลงในหน่วยความจำและเก็บไว้ในข้อความธรรมดาจนกว่าจะรวบรวมขยะ) อย่างไรก็ตามคุณสามารถเพิ่มอักขระใน SecureString ได้โดยการต่อท้าย
var s = new SecureString();
s.AppendChar('d');
s.AppendChar('u');
s.AppendChar('m');
s.AppendChar('b');
s.AppendChar('p');
s.AppendChar('a');
s.AppendChar('s');
s.AppendChar('s');
s.AppendChar('w');
s.AppendChar('d');
*****
AppendChar
ไม่ดำเนินการจนกว่าจะถึงเวลารันดังนั้นอักขระเหล่านั้นยังสามารถอ่านได้จาก IL ถูกต้องหรือไม่? บางทีการสับสนในเวลาคอมไพล์อาจช่วยได้เช่นกัน ... นั่นคือถ้าคุณเข้ารหัสรหัสผ่านยาก
นอกจากนี้ยังมีวิธีการแปลงระหว่างอื่นและSecureString
String
1. สตริงเป็น SecureString
SecureString theSecureString = new NetworkCredential("", "myPass").SecurePassword;
2. SecureString เป็น String
string theString = new NetworkCredential("", theSecureString).Password;
ที่นี่คือ ลิงค์
SecureString
if รหัสของคุณสร้างstring
วัตถุด้วยค่าที่คุณต้องการรักษาความปลอดภัย เป้าหมายSecureString
คือการหลีกเลี่ยงการมีสตริงในหน่วยความจำที่มีการจัดการดังนั้นผู้โจมตีที่ตรวจสอบหน่วยความจำนั้นสามารถมองเห็นค่าที่คุณต้องการซ่อนได้ เนื่องจากตัวNetworkCredential
สร้างที่คุณเรียกใช้ต้องใช้สตริงจึงไม่ใช่วิธีที่จะไป ... แน่นอนว่ารหัสของคุณเป็นวิธีที่ง่ายในการแปลงไปยังและกลับจาก SecureString แต่การใช้งานจะทำให้รหัสของคุณปลอดภัยเท่ากับการใช้งานง่ายstring
SecureString
เมื่อทำงานกับห้องสมุดบางแห่ง และขอบอกตามตรงว่าหากมีคนกำลังสแกนหน่วยความจำของแอปพลิเคชันของคุณแสดงว่าคุณทำหายไปแล้ว แม้ว่าคุณจะใช้ SecureString อย่างถูกต้องซึ่งฉันไม่เคยเห็นมาก่อน แต่ก็มีข้อมูลที่มีค่าอื่น ๆ ให้ดึงออกมา
วิธีการด้านล่างช่วยในการแปลงสตริงเป็นสตริงที่ปลอดภัย
private SecureString ConvertToSecureString(string password)
{
if (password == null)
throw new ArgumentNullException("password");
var securePassword = new SecureString();
foreach (char c in password)
securePassword.AppendChar(c);
securePassword.MakeReadOnly();
return securePassword;
}
คุณสามารถทำตามสิ่งนี้:
string password = "test";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();
นี่คือเคล็ดลับ linq ราคาถูก
SecureString sec = new SecureString();
string pwd = "abc123"; /* Not Secure! */
pwd.ToCharArray().ToList().ForEach(sec.AppendChar);
/* and now : seal the deal */
sec.MakeReadOnly();
ฉันจะโยนสิ่งนี้ออกไป ทำไม?
คุณไม่สามารถเปลี่ยนสตริงทั้งหมดของคุณเพื่อรักษาความปลอดภัยสตริงและทันใดนั้นแอปพลิเคชันของคุณก็ "ปลอดภัย" สตริงที่ปลอดภัยได้รับการออกแบบมาเพื่อให้สตริงเข้ารหัสให้นานที่สุดเท่าที่จะเป็นไปได้และจะถูกถอดรหัสในช่วงเวลาสั้น ๆ เท่านั้นโดยจะเช็ดหน่วยความจำหลังจากดำเนินการไปแล้ว
ฉันจะบอกว่าคุณอาจมีปัญหาระดับการออกแบบที่ต้องจัดการก่อนที่จะกังวลเกี่ยวกับการรักษาความปลอดภัยสตริงแอปพลิเคชันของคุณ ให้ข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่คุณพยายามทำและเราอาจช่วยได้ดีขึ้น
unsafe
{
fixed(char* psz = password)
return new SecureString(psz, password.Length);
}
ไม่มี linq แฟนซีไม่ได้เพิ่มตัวอักษรทั้งหมดด้วยมือเพียงธรรมดาและเรียบง่าย:
var str = "foo";
var sc = new SecureString();
foreach(char c in str) sc.appendChar(c);
var sc = new SecureString(); foreach(char c in "foo") sc.appendChar(c);
ฉันเห็นด้วยกับ Spence (+1) แต่ถ้าคุณทำเพื่อการเรียนรู้หรือทดสอบการเทคุณสามารถใช้ foreach ในสตริงโดยต่อท้ายอักขระแต่ละตัวเข้ากับสตริงที่ปลอดภัยโดยใช้เมธอด AppendChar
ฉันแค่อยากจะชี้ให้ทุกคนเห็นว่า "นั่นไม่ใช่ประเด็นSecureString
" ซึ่งหลาย ๆ คนที่ถามคำถามนี้อาจอยู่ในแอปพลิเคชันที่ไม่ว่าด้วยเหตุผลใดจะเป็นธรรมหรือไม่ก็ตามพวกเขาไม่ได้กังวลเป็นพิเศษเกี่ยวกับการมี สำเนาชั่วคราวของรหัสผ่านจะอยู่บนฮีปเป็นสตริงที่รองรับ GC แต่ต้องใช้ API ที่ยอมรับเฉพาะอSecureString
อบเจ็กต์ ดังนั้นคุณมีแอปที่คุณไม่สนใจไม่ว่ารหัสผ่านจะอยู่ในฮีปหรือไม่อาจเป็นรหัสผ่านสำหรับใช้งานภายในเท่านั้นและรหัสผ่านจะอยู่ที่นั่นเพียงเพราะต้องการโดยโปรโตคอลเครือข่ายพื้นฐานและคุณพบว่าไม่สามารถใช้สตริงนั้นที่เก็บรหัสผ่านเพื่อตั้งค่า PowerShell ระยะไกลได้ Runspace - แต่ไม่มีอะไรง่ายตรงไปตรงมาหนึ่งซับในการสร้างสิ่งSecureString
ที่คุณต้องการ มันเป็นความไม่สะดวกเล็ก ๆ น้อย ๆ - แต่อาจจะคุ้มค่าที่จะให้แน่ใจว่าการใช้งานที่จริงๆทำต้องSecureString
ไม่ล่อใจผู้เขียนจะใช้System.String
หรือSystem.Char[]
ตัวกลาง :-)
หากคุณต้องการบีบอัดการแปลงstring
a SecureString
เป็นLINQ
คำสั่งคุณสามารถแสดงได้ดังนี้:
var plain = "The quick brown fox jumps over the lazy dog";
var secure = plain
.ToCharArray()
.Aggregate( new SecureString()
, (s, c) => { s.AppendChar(c); return s; }
, (s) => { s.MakeReadOnly(); return s; }
);
อย่างไรก็ตามโปรดทราบว่าการใช้LINQ
ไม่ได้ช่วยเพิ่มความปลอดภัยของโซลูชันนี้ มันทนทุกข์ทรมานจากข้อบกพร่องเช่นเดียวกับการแปลงใด ๆ จากการstring
SecureString
ตราบเท่าที่ต้นฉบับstring
ยังคงอยู่ในหน่วยความจำข้อมูลก็มีช่องโหว่
ดังที่กล่าวไว้สิ่งที่ข้อความข้างต้นสามารถนำเสนอได้คือการรวบรวมการสร้างการSecureString
เริ่มต้นด้วยข้อมูลและในที่สุดก็ล็อคไม่ให้แก้ไข
2 ส่วนขยายต่อไปนี้ควรทำเคล็ดลับ:
สำหรับchar
อาร์เรย์
public static SecureString ToSecureString(this char[] _self)
{
SecureString knox = new SecureString();
foreach (char c in _self)
{
knox.AppendChar(c);
}
return knox;
}
และสำหรับ string
public static SecureString ToSecureString(this string _self)
{
SecureString knox = new SecureString();
char[] chars = _self.ToCharArray();
foreach (char c in chars)
{
knox.AppendChar(c);
}
return knox;
}
ขอบคุณJohn DaggสำหรับAppendChar
คำแนะนำ
คุณสามารถใช้สคริปต์ง่ายๆนี้
private SecureString SecureStringConverter(string pass)
{
SecureString ret = new SecureString();
foreach (char chr in pass.ToCharArray())
ret.AppendChar(chr);
return ret;
}
12345
... นั่นคือสิ่งที่คนโง่มีอยู่ในกระเป๋าของเขา!"