String'i SecureString'e Dönüştür


Yanıtlar:


137

Yapmıyorsun. SecureString nesnesini kullanmanın tüm nedeni, bir dizgi nesnesi oluşturmaktan kaçınmaktır (bu, belleğe yüklenir ve çöp toplamaya kadar orada düz metin olarak tutulur). Ancak, SecureString'e karakterleri ekleyerek ekleyebilirsiniz.

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');

13
"Kombinasyon 12345... bir aptalın valizinde taşıdığı türden bir şey!"
Kolob Canyon

8
Tek gördüğüm*****
Ian Boyd

AppendCharçalışma zamanına kadar çalışmaz, bu nedenle bu karakterler hala IL'den okunabilir, değil mi? Belki derleme zamanı gizlemesi de yardımcı olabilir ... yani, şifreleri sabit kodluyorsanız.
samis

5
Bu berbat bir argüman. Parolayı nereden alıyorsun? Bir formdan veya komut satırından. Doğrudan bir cihazdan veya komut satırı argümanlarından güvenli bir dizeyi okumak için bir yöntem oluşturana kadar, bir dizeyi SecureString'e dönüştürmemiz gerekir.
Quarkly

1
@DonaldAirey bir sırlar yöneticisinden bir şifre alırsınız. Genel olarak burada bahsettiğimiz sırlar kullanıcı şifreleri değil, potansiyel olarak ayrıcalık artışına veya veri sızıntılarına neden olan şeylerdir. Bu, şifrelerin diğer hizmetler için olduğu ve komut satırlarında veya ağ kanalları üzerinden açık olarak aktarılmaması gerektiği anlamına gelir.
Barry Kelly

160

SecureStringVe arasında dönüştürme yapmanın başka bir yolu daha var String.

1. SecureString'e Dize

SecureString theSecureString = new NetworkCredential("", "myPass").SecurePassword;

2. SecureString'den Dizeye

string theString = new NetworkCredential("", theSecureString).Password;

İşte bağlantı


4
Bu, en yaygın kullanım durumu için en iyi çözümdür!
Dan Bechard

16
SecureStringKodunuz string, güvence altına almak istediğiniz değere sahip bir nesne oluşturuyorsa, a kullanmanın bir anlamı yoktur . Amacı SecureString, dizenin yönetilen bellekte yer almasından kaçınmaktır, böylece bu belleği inceleyen bir saldırgan, gizlemek istediğiniz değeri tespit edebilir. Yana NetworkCredentialAradığınız yapıcı ... Emin gitmek yol değil bir dize gerektirir, kodunuz ve bir SecureString dan dönüştürmek için kolay bir yoldur, ama bunu kullanarak bir basit kullanma gibi güvenli kodunuzu yaparstring
Gian Paolo

15
@GianPaolo Bu teoride doğru olsa da, pratikte SecureStringbazı kütüphanelerle çalışırken hala kullanmamız gerekiyor . Ve burada dürüst olalım, eğer birisi uygulamanızın belleğini aktif olarak tarıyorsa, o zaman zaten kaybettiniz demektir. SecureString'i daha önce hiç görmediğim şekilde doğru kullanmış olsanız bile, çıkarılacak başka değerli veriler olacaktır.
Jonathan Allen

1
@JonathanAllen: Muhtemelen haklısın, ama sadece güvenliği sonradan düşündüğümüz bir kültürümüz olduğu için. Bir tarif web sitesi oluşturuyorsanız, Kuzey Kore muhtemelen programınızın belleğini taramaya çalışmaz. Bankacılık yazılımı yazıyorsanız, tehdit çok daha gerçektir.
Eric J.

58

Aşağıdaki yöntem, dizeyi güvenli dizeye dönüştürmeye yardımcı olur

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;
}

26
+1, ancak şifreyi bir dize parametresi olarak geçirmenin yönetilen bellekte şifrelenmemiş bir dize örneği oluşturduğunu ve ilk etapta 'SecureString'in amacını bozduğunu unutmayın. Sadece gelip bu kodu kullanan gelecekteki insanlar için bunu işaret ediyorum.
Cody

19
@Cody Bu doğru ve iyi bir nokta, ancak çoğumuz SecureString'in güvenli olup olmadığı umurumuzda değil ve yalnızca bazı Microsoft API'leri bunu bir parametre olarak gerektirdiği için kullanıyoruz.
Dan Bechard

3
@Cody SecureString sınıfının bile dizeyi şifreli tutamayacağı ortaya çıktı. Bu nedenle MS, github.com/dotnet/platform-compat/blob/master/docs/DE0001.md türünü geçersiz kılmayı düşünüyor .
Martin Brown

19

Bunu takip edebilirsiniz:

string password = "test";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();

11

İşte ucuz bir linq numarası.

            SecureString sec = new SecureString();
            string pwd = "abc123"; /* Not Secure! */
            pwd.ToCharArray().ToList().ForEach(sec.AppendChar);
            /* and now : seal the deal */
            sec.MakeReadOnly();

32
Bu cevap, düz metnin kaç tane geçici kopyasının tek seferde oluşturulabileceğini görmektir
Mike Caron

1
@ john-dagg'ın önerdiği gibi, fikir şifrenizle bir dize OLMAMAKTIR, çünkü bunu yaparsanız, bir güvenlik zinciri kullanmanın bir avantajı kalmaz. Sizin durumunuzda şifreyi düz metin olarak girmişseniz, daha sonra bir emniyet kemeri kullanarak hiçbir şeyi güvence altına alamazsınız. Umarım güvenliğin dizginizi sökme veya hata ayıklayıcıya bakan insanlardan korumak olduğunu anlamışsınızdır, bu yüzden IL / bellekte ne olduğunu görün.
user734028

8

Bunu oraya atacağım. Neden?

Dizeleri güvenli hale getirmek için tüm dizelerinizi değiştiremezsiniz ve aniden uygulamanız "güvenli" olur. Güvenli dize, dizeyi olabildiğince uzun süre şifrelenmiş halde tutmak için tasarlanmıştır ve yalnızca çok kısa bir süre için şifresi çözülerek, üzerinde bir işlem gerçekleştirildikten sonra belleği siler.

Uygulama dizelerinizin güvenliğini sağlamak için endişelenmeden önce ilgilenmeniz gereken bazı tasarım düzeyi sorunlarınız olabileceğini söyleyemem. Ne yapmaya çalıştığınız hakkında bize biraz daha bilgi verin, size daha iyi yardımcı olabiliriz.


1
Sadece ProcessStartInfo için parola ayarlamak ve exe'mi farklı bir kullanıcı olarak çalıştırmak için kullanmak istiyorum .. Bu benim için çalıştı ...
Developer404

4
Uygulamam güvenli bir sistemde çalıştırılarak güvence altına alındı. Bu dizgenin bellekte şifrelenmesi umurumda bile olamazdı. Bu sistemde, herhangi bir şekilde tehlikeye atılması durumunda endişelenmeniz gereken çok daha hayati bilgiler var. SecureString, programımın kullanması gereken bir Microsoft API tarafından basitçe gereklidir. Geliştiricinin kendi kullanım durumunu göz önünde bulundurması ve Strings'i SecureStrings'e dönüştürmenin bağlamda geçerli bir işlem olup olmadığını belirlemesi ima edilir.
Dan Bechard

Yani bu yöntem, DotPeek gibi bir derleyiciyi kullanan birinin parolayı görmesini engellemeyecek mi? Bu durumda dizeleri gizlemenin bir yolu var mı?
M.Parent

Yenmeye çalıştığınız tehdide bağlı olarak birkaç yöntem var. Kullanıcı bilgilerini yerel yönetici dışındaki herhangi birinden korumak için, bir dosyayı şifrelemek ve orada bir sır saklamak için DPAPI yöntemlerini kullanabilir, onu güvenli bir dizede okuyabilir ve sonra atabilirsiniz. Bir şirket sırrı içinse, kısa cevap, uygulamanızın şifresini çözüp çözemeyeceğidir, kullanıcı da sonunda çözebilir.
Spence

6
unsafe 
{
    fixed(char* psz = password)
        return new SecureString(psz, password.Length);
}

5

süslü bağlantı yok, tüm karakterleri elle eklemiyor, sadece sade ve basit:

var str = "foo";
var sc = new SecureString();
foreach(char c in str) sc.appendChar(c);

daha da meraklısı, değişken tanımlamaya gerek yok
bigworld12

işte tek bir var sc = new SecureString(); foreach(char c in "foo") sc.appendChar(c);
satır

4

Spence (+1) 'e katılıyorum, ancak bunu döküntüleri öğrenmek veya test etmek için yapıyorsanız, dizide bir foreach kullanabilir, her bir karakteri AppendChar yöntemini kullanarak güvenliğe ekleyebilirsiniz.


3

Sadece "böyle en değil noktası tüm insanlar söyleyerek işaret etmek istiyorum SecureStringbu soruyu soran insanların çoğu ne olursa olsun haklı ya da değil sebebi, için, onlar vardır, bir uygulamada olabileceğini," değil özellikle sahip endişe şifrenin geçici bir kopyası, yığın üzerinde GC uyumlu bir dize olarak bulunur, ancak yalnızcaSecureString nesneleri kabul eden bir API kullanmaları gerekir . Yani, umursamadığınız bir uygulamanız varParola yığın üzerinde olsun, belki yalnızca dahili kullanımdır ve parola yalnızca temeldeki ağ protokolleri tarafından gerekli olduğu için mevcuttur ve parolanın depolandığı dizenin, örneğin uzak bir PowerShell kurmak için kullanılamayacağını görürsünüz. Runspace - ancak SecureStringihtiyacınız olanı yaratmak için kolay, doğrudan tek satırlık bir yol yoktur . Bu küçük bir rahatsızlıktır - ancak gerçekten işe yarayan uygulamaların gerek SecureStringkullanımına yazarlar zorlama System.Stringveya System.Char[]aracılar. :-)


2

Eğer bir dönüşüm sıkıştırmak isterseniz stringbir karşı SecureStringbir içine LINQaçıklamada şöyle bunu ifade edebiliriz:

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; }
                       );

Ancak, kullanmanın LINQbu çözümün güvenliğini artırmadığını unutmayın . Bu herhangi bir dönüşümle aynı kusur muzdarip stringiçin SecureString. Orijinal stringbellekte kaldığı sürece veriler savunmasızdır.

Bununla birlikte, yukarıdaki ifadenin sunabileceği şey SecureString, verinin oluşturulmasını , başlatılmasını verilerle bir arada tutmak ve son olarak onu değişiklikten kilitlemektir.


2

Aşağıdaki 2 uzantı hile yapmalı:

  1. Bir chardizi için

    public static SecureString ToSecureString(this char[] _self)
    {
        SecureString knox = new SecureString();
        foreach (char c in _self)
        {
            knox.AppendChar(c);
        }
        return knox;
    }
  2. Ve için 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;
    }

Tavsiye için John Dagg'a teşekkürler AppendChar.


0

bu basit betiği kullanabilirsin

private SecureString SecureStringConverter(string pass)
{
    SecureString ret = new SecureString();

    foreach (char chr in pass.ToCharArray())
        ret.AppendChar(chr);

    return ret;
}

1
Bu cevap 15 ay önce gönderildi . Gerçekten tekrar göndermeye gerek yoktu.
GSerg
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.